Bind To Model

At this point we have created an Entity Framework model as well as the static html, css, and images that produce the desired look and feel of the task board.  Now it's time to bring the two together.  When this step is complete our application will render the same HTML dynamically for the data stored in the database.

The first thing we will do is use ExoWeb to generate a projection of our entites as JavaScript objects.  The code required to do this is short and sweet.

@ExoWeb.Model(new 

{

    user = Model.Include("Lists.Items""Priority.All")

})

The ExoWeb.Model method is used to query our entities for the data the we will use on the client. The parameter to the method is an anonymous object, where the name of each property will be used as the name of a "root" for our model context, and its value will be the value of the root. The Include() extension method is used to specify additional paths to data that we will be using on the page.

Now, from our browser's console we can access the "user" root and related data like so:

> context.model.user.toString()

"William"

> context.model.user.get_Lists().length

1

> context.model.user.get_Lists()[0].get_Name()

"My First List"

> context.model.user.get_Lists()[0].get_Items().length

1

> context.model.user.get_Lists()[0].get_Items()[0].get_Description()

"Be Productive!"

 

The next step is to augment our static HTML so that it is dynamically generated:

@ExoWeb.Render(@<div class="sys-template board" sys:attach="dataview" dataview:data="{~ context.model.user, source=window }">

       <div class="board-title">

              <span class="board-user">{# Name}</span>

              <a class="board-addlist" href="#" onclick="return false;">Add a list..</a>

              <span class="board-status">

                     <span class="board-server-working">Communicating with the server...</span>

                     <span class="board-server-success">Success</span>

                     <span class="board-server-failure">An error occurred!</span>

                     <a href="#" onclick="return false;">Try again</a>

              </span>

       </div>

       <div class="sys-template board-background" sys:attach="dataview" dataview:data="{~ Lists, transform=orderBy('Sequence') }">

              <div class="board-list">

                     <div class="board-list-title">

                           <strong>{# Name}</strong>

                           <span class="board-deletelist"></span>

                     </div>

                     <div class="sys-template board-list-content sortable" sys:attach="dataview" dataview:data="{~ Items, transform=orderBy('Sequence') }">

                           <div sys:class="{# Priority.Name}">

                                  <div class="board-list-item">

                                         <div class="board-list-item-text">

                                                <span class="board-list-item-sequence"><span>{# Sequence}</span>: </span>

                                                <span>{# Description}</span>

                                         </div>

                                         <div class="board-list-item-age-description">Item Age Description (eg, one minute ago)</div>

                                         <span class="board-list-item-priority"></span>

                                         <a class="board-list-deleteitem" href="#" onclick="return false;"></a>

                                  </div></div></div>

                     <div class="board-list-additem">

                           <input type="text" style="display:none;" value="" />

                           <a href="#" onclick="return false;">Add an item...</a></div>

              </div>

       </div>

</div>)

First, we have wrapped the static HTML in a method call to ExoWeb.Render.  This causes the server-side templating engine to generate dynamic markup, and also enables the browser to update the markup as changes are made client-side.

In addition to enabling template rendering we must also make the markup dyanamic.  The changes necessary to make that happen have been highlighted. We have added a special class, "sys-template", which tells the templating engine that an element is special.  The sys:attach attribute signifies that a control should be attached to the element, where the value of the attribute is the name of the control to attach.  The control in this case is a dataview, which is used to create a new "data binding context" on the page.  In other words, it links data to a block of HTML, and when the data changes the DOM is updated to reflect the changes.  The value of the data property tells the templating engine how to bind to the model.

The templating engine can also bind the value of a property to the text of an element.  We use this feature to display the user's name, each list's name, and the description of each task.

With all of this in place, our board now displays the data that is stored in the database...minus the description of the item's age (more on that later).


  1. Insert the following code snippet into Views\Home\Index.cshtml, before the Main board interface:
    @*
    Exo-model declaration
    *@
    
    @ExoWeb.Model(new 
    {
    	user = Model.Include("Lists.Items", "Priority.All")
    })
    				
  2. Insert the following code snippet into Views\Home\Index.cshtml, after the Main board interface, replacing the existing static markup:
    @ExoWeb.Render(@<div class="sys-template board" sys:attach="dataview" dataview:data="{~ context.model.user, source=window }">
    	<div class="board-title">
    		<span class="board-user">{# Name}</span>
    		<a class="board-addlist" href="#" onclick="return false;">Add a list..</a>
    	</div>
    	<div class="sys-template board-background" sys:attach="dataview" dataview:data="{~ Lists, transform=orderBy('Sequence') }">
    		<div class="board-list">
    			<div class="board-list-title">
    				<strong>{# Name}</strong>
    				<span class="board-deletelist"></span>
    			</div>
    			<div class="sys-template board-list-content sortable" sys:attach="dataview" dataview:data="{~ Items, transform=orderBy('Sequence') }">
    				<div sys:class="{# Priority.Name}">
    					<div class="board-list-item">
    						<div class="board-list-item-text">
    							<span>{# Description}</span>
    						</div>
    						<div class="board-list-item-age-description">Item Age Description (eg, one minute ago)</div>
    						<span class="board-list-item-priority"></span>
    						<a class="board-list-deleteitem" href="#" onclick="return false;"></a>
    					</div></div></div>
    			<div class="board-list-additem">
    				<input type="text" style="display:none;" value="" />
    				<a href="#" onclick="return false;">Add an item...</a></div>
    		</div>
    	</div>
    </div>)