The question: How can I structure my code so that the knockout bindings are not applied until all of the queries for the ViewModel have been executed?
Update: After some further research and experimentation I think that using something along the lines of a Deferred function may work. I have tried a few implementations, however it only defers until the query is called, rather than until all query results have been processed. I'm obviously doing something wrong here but my javascript foo is weak.
Technologies used: Entity Framework 5 w/ Oracle, .Net 4 Web API, Knockout 2.2, Breeze 0.71.3
The situation: Breeze is being used to call a Web API method which retrieves an Enumerable of POCOs, populates a knockout observable array, and the array is bound to a select control in the View.
The problem: The breeze queries have not completed and the knockout observables have not been populated prior to applying the ViewModel bindings to the View. When the query results are returned, the UI is unresponsive for 5 - 7 secs while the ko observable is populated and thus the select control is updated. Based on the logging this appears to be the issue...
The cshtml file:
<select data-bind="options: $root.brokers, value: 'id', optionsText: 'name'">
<script data-main="/BrokerCommission/Scripts/app/main" src="/BrokerCommission/Scripts/require.js"></script>
main.js:
requirejs.config(
{
// well-know paths to selected scripts
paths: {
'breeze': '../breeze.debug', // debug version of breeze
'text': '../text'// html loader plugin; see http://requirejs.org/docs/api.html#text
}
}
);
define(['logger', 'text', 'breeze'], function(logger) {
require(['vm.muni'],
function()
{
logger.info('applying bindings');
ko.applyBindings(my.vm);
});
vm.muni is my ViewModel javascript file. Here's a method being exposed to exec a query:
getAllBrokers = function () {
dataservice.getBrokers()
.then(processBrokerQueryResults)
.fail(handleQueryErrors);
},
processBrokerQueryResults = function (data) {
logger.info("Start loading Brokers " + Math.round(new Date().getTime() / 1000));
my.vm.brokers([]);
$.each(data.results, function (i, d) {
brokers.push(new my.Broker()
.id(d.id)
.name(d.name)
);
});
logger.info("End loading Brokers " + Math.round(new Date().getTime() / 1000));
},
Here is the breeze query from dataservice.js file:
function getBrokers() {
var query = new entityModel.EntityQuery()
.from("GetBrokers")
//.orderBy("name");
return manager.executeQuery(query);
};