title: Binding Issues with KnockoutJs and Breeze - Navigation Properties
body: <p>My app is based on the HotTowel template so it includes Durandal, Knockout &amp; Breeze.  I have a page with 3 tables side by side.  The first table has a list of "templates', the 2nd table shows "sections" for the selected "template" and the 3rd table shows "items" for the selected "section".  The "sections" and "items" tables are collections accessed via navigation properties.  I find that I get intermittent binding issues.  The data in the "templates" table always shows correctly, however related "sections" and "items" sometimes show correctly and other times one of the other is not populated.  It would seem to be a timing issue.  My view model and view are below.  Am I just going about all of this the wrong way?</p>
  
  <pre><code>define(['services/dataservice', 'services/logger', 'services/model'],
      function (ds, logger, model) {
          var templates = ko.observableArray();
          var selectedTemplate = ko.observable();
          var selectedSection = ko.observable();
          var selectedItem = ko.observable();
          var newTemplateTitle = ko.observable();
          var newSectionTitle = ko.observable();
          var newItemTitle = ko.observable();
  
          function activate() {
              newTemplateTitle('');
              newSectionTitle('');
              newItemTitle('');
              logger.log('Templates view activated', null, 'templates', false);
              return ds.getTemplatePartials(templates, false, false);//.then(succeeded);
  
              //function succeeded() {
              //    var firstTemplate = templates()[0];
              //    setSelectedTemplate(firstTemplate);
              //}
          }
  
          templates.subscribe(function() {
              var firstTemplate = templates()[0];
              setSelectedTemplate(firstTemplate);
          });
  
          var deactivate = function () {
              templates([]);
          };
  
          function refresh() {
              return ds.getTemplatePartials(templates, true, false);
          }
  
          var viewAttached = function (view) {
              bindEventToList(view, '#template-list', setSelectedTemplate);
              bindEventToList(view, '#section-list', setSelectedSection);
              bindEventToList(view, '#item-list', setSelectedItem);
              return true;
          };
  
          var addTemplate = function () {
              var newTemplate = ds.createEntity(model.entityNames.document);
              newTemplate.title(newTemplateTitle());
              newTemplate.isTemplate(true);
              newTemplate.organisation(ds.getCurrentOrganisation()());
              return ds.saveChanges().then(saveSucceeded);
  
              function saveSucceeded() {
                  templates.push(newTemplate);
                  templates.sort();
                  newTemplateTitle('');
              }
          };
  
          var addSection = function () {
              var newSection = ds.createEntity(model.entityNames.section);
              newSection.title(newSectionTitle());
              newSection.isTemplate(true);
              newSection.document(selectedTemplate());
              return ds.saveChanges().then(saveSucceeded);
  
              function saveSucceeded() {
                  newSectionTitle('');
              }
          };
  
          var addItem = function () {
              var newItem = ds.createEntity(model.entityNames.item);
              newItem.title(newItemTitle());
              newItem.isTemplate(true);
              newItem.section(selectedSection());
              return ds.saveChanges().then(saveSucceeded);
  
              function saveSucceeded() {
                  newItemTitle('');
              }
          };
  
          var isTemplateSelected = function (template) {
              if (template &amp;&amp; selectedTemplate()) {
                  var thisId = ko.utils.unwrapObservable(selectedTemplate().id);
                  return ko.utils.unwrapObservable(template.id) == thisId;
              }
  
              return false;
          };
  
          var isSectionSelected = function (section) {
              if (section &amp;&amp; selectedSection()) {
                  var thisId = ko.utils.unwrapObservable(selectedSection().id);
                  return ko.utils.unwrapObservable(section.id) == thisId;
              }
  
              return false;
          };
  
          var isItemSelected = function(item) {
              if (item &amp;&amp; selectedItem()) {
                  var thisId = ko.utils.unwrapObservable(selectedItem().id);
                  return ko.utils.unwrapObservable(item.id) == thisId;
              }
  
              return false;
          };
  
          var vm = {
              activate: activate,
              deactivate: deactivate,
              templates: templates,
              //sections: sections,
              //items: items,
              selectedTemplate: selectedTemplate,
              selectedSection: selectedSection,
              selectedItem: selectedItem,
              title: 'Template Maintenance',
              refresh: refresh,
              viewAttached: viewAttached,
              addTemplate: addTemplate,
              addSection: addSection,
              addItem: addItem,
              newTemplateTitle: newTemplateTitle,
              newSectionTitle: newSectionTitle,
              newItemTitle: newItemTitle,
              isTemplateSelected: isTemplateSelected,
              isSectionSelected: isSectionSelected,
              isItemSelected: isItemSelected
          };
  
          return vm;
  
          //#region internal methods
          function setSelectedTemplate(data) {
              if (data) {
                  selectedTemplate(data);
                  return selectedTemplate().entityAspect.loadNavigationProperty("sections").then(setFirstSectionSelected);
              } else {
                  return false;
              }
  
              function setFirstSectionSelected() {
                  setSelectedSection(selectedTemplate().sections()[0]);
              }
          }
  
          function setSelectedSection(data) {
              if (data) {
                  selectedSection(data);
                  return selectedSection().entityAspect.loadNavigationProperty("items").then(setFirstItemSelected);
              } else {
                  selectedSection();
                  selectedItem();
                  return false;
              }
  
              function setFirstItemSelected() {
                  setSelectedItem(selectedSection().items()[0]);
              }
          }
  
          function setSelectedItem(data) {
              if (data) {
                  selectedItem(data);
              } else {
                  selectedItem();
              }
          }
  
          function bindEventToList(rootSelector, selector, callback, eventName) {
              var eName = eventName || 'click';
              $(rootSelector).on(eName, selector, function () {
                  var item = ko.dataFor(this); 
                  callback(item);
                  return false;
              });
          }
          //#region
      }
  );
  
  &lt;section&gt;
  &lt;div class="row-fluid"&gt;
      &lt;header class="span12"&gt;
          &lt;button class="btn btn-info pull-right push-down10" data-bind="click: refresh"&gt;
              &lt;i class="icon-refresh"&gt;&lt;/i&gt; Refresh&lt;/button&gt;
          &lt;h4 class="page-header" data-bind="text: title"&gt;&lt;/h4&gt;
      &lt;/header&gt;
  &lt;/div&gt;
  
  &lt;div class="row-fluid"&gt;
      &lt;section class="span3"&gt;
          &lt;header class="input-append"&gt;
              &lt;input id="newTemplateName"
                     type="text"
                     data-bind="realTimeValue: newTemplateTitle" 
                     placeholder="New template name"
                     class="input-medium" /&gt;
              &lt;button class="btn btn-info add-on" data-bind="click: addTemplate, disable: newTemplateTitle() === ''"&gt;
                  &lt;i class="icon-plus"&gt;&lt;/i&gt; Add&lt;/button&gt;
          &lt;/header&gt;
  
          &lt;article&gt;
              &lt;table class="table table-striped table-bordered table-hover"&gt;
                  &lt;thead&gt;
                      &lt;tr&gt;
                          &lt;th&gt;Templates&lt;/th&gt;
                      &lt;/tr&gt;
                  &lt;/thead&gt;
                  &lt;tbody&gt;
                  &lt;!-- ko foreach: templates --&gt;
                      &lt;tr id="template-list" data-bind="css: { 'selected': $root.isTemplateSelected($data) }"&gt;
                          &lt;td data-bind="text: title" /&gt;
                      &lt;/tr&gt;
                  &lt;!-- /ko --&gt;
                  &lt;/tbody&gt;
              &lt;/table&gt;
              &lt;span&gt;Count: &lt;span data-bind="text: templates().length"&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;/article&gt;
      &lt;/section&gt;
  
      &lt;section class="span5"&gt;
          &lt;header class="input-append"&gt;
              &lt;input id="newSectionName"
                     type="text"
                     data-bind="realTimeValue: newSectionTitle" 
                     placeholder="New section name"
                     class="input-medium" /&gt;
              &lt;button class="btn btn-info add-on" data-bind="click: addSection, disable: newSectionTitle() === ''"&gt;
                  &lt;i class="icon-plus"&gt;&lt;/i&gt; Add&lt;/button&gt;
          &lt;/header&gt;
  
          &lt;article data-bind="if: selectedTemplate"&gt;
              &lt;table class="table table-striped table-bordered table-hover" &gt;
                  &lt;thead&gt;
                      &lt;tr&gt;
                          &lt;th data-bind="text: 'Sections for ' + selectedTemplate().title()"&gt;&lt;/th&gt;
                      &lt;/tr&gt;
                  &lt;/thead&gt;
                  &lt;tbody&gt;
                  &lt;!-- ko foreach: selectedTemplate().sections() --&gt;
                      &lt;tr id="section-list" data-bind="css: { 'selected': $root.isSectionSelected($data) }"&gt;
                          &lt;td data-bind="text: title" /&gt;
                      &lt;/tr&gt;
                  &lt;!-- /ko --&gt;
                  &lt;/tbody&gt;
              &lt;/table&gt;
              &lt;span&gt;Count: &lt;span data-bind="text: selectedTemplate().sections().length"&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;/article&gt;
      &lt;/section&gt;
  
      &lt;section class="span4"&gt;
          &lt;header class="input-append"&gt;
              &lt;input id="newItemName"
                     type="text"
                     data-bind="realTimeValue: newItemTitle" 
                     placeholder="New item name"
                     class="input-medium" /&gt;
              &lt;button class="btn btn-info add-on" data-bind="click: addItem, disable: newItemTitle() === ''"&gt;
                  &lt;i class="icon-plus"&gt;&lt;/i&gt; Add&lt;/button&gt;
          &lt;/header&gt;
  
          &lt;article data-bind="if: selectedSection"&gt;
              &lt;table class="table table-striped table-bordered table-hover"&gt;
                  &lt;thead&gt;
                      &lt;tr&gt;
                          &lt;th data-bind="text: 'Items for ' + selectedSection().title()"&gt;&lt;/th&gt;
                      &lt;/tr&gt;
                  &lt;/thead&gt;
                  &lt;tbody&gt;
                  &lt;!-- ko foreach: selectedSection().items() --&gt;
                      &lt;tr id="item-list" data-bind="css: { 'selected': $root.isItemSelected($data) }"&gt;
                          &lt;td data-bind="text: title" /&gt;
                      &lt;/tr&gt;
                  &lt;!-- /ko --&gt;
                  &lt;/tbody&gt;
              &lt;/table&gt;
              &lt;span&gt;Count: &lt;span data-bind="text: selectedSection().items().length"&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;/article&gt;
      &lt;/section&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p></p>