My goal is simply to generate a viewModel via Knockout.Mapping, bind a igGrid to the viewModel, and then refresh the viewModel and grid via an ajax call to a controller that returns JSON. I am using VisualStudio 2013 and MVC 5. I have the correct libraries referenced. I am able to get the Infragistics Knockout Integration sample to work correctly, but in the sample there are a lot of hard coded references to column names. I don't want to reference the column names directly, but rather rely on knockout mapping to create my observable viewModel. The initial model binding works fine, and the populated grid is correctly displayed. When I attempt to refresh the grid after the Ajax call, the browser freezes and I have to terminate IE. Can someone show me a simple example of how this can be accomplished?
HTML - <table id="grid" data-bind="igGrid: { dataSource: myData, primaryKey: 'ID', features: [{ name: 'Updating', editMode: 'none', enableAddRow: false, enableDeleteRow: true, columnSettings: [ ] }] }"></table>
JavaScript -
$(document).ready(function () {
var model = @Html.Raw(Json.Encode(Model))
viewmodel = ko.mapping.fromJS(model)
ko.applyBindings(viewmodel); };
function getRefreshedModel()
{
$.ajax({
url:"/Controller/Action/",
type:'post',
data: dataString,
contentType:'application/json',
success: function (results) { ko.mapping.fromJS(results, viewmodel); } //refresh the model and grid
});
}
Hello,
When you try to reload your view model with a new set of data, the grid will try to find the differences between the two and apply them without re-rendering itself. This is one of the key features of the grid's Knockout integration, however it can be slow with very big chunks of data, which might be what's causing this freezing. What is the amount of records the server sends in your case? Could you please share which version of Ignite UI you are using?
I am looking forward to hearing from you!
Best regards,
Stamen Stoychev
Hi,
I don't think it is a recordsize issue because I am only returning about 100 results. Is it possible to do without hand coding the view model and just using mapping plug in? The example Infragistics provides is mapped by hand.
I believe that I am using the latest version of igniteUI, which is in the download is a subfolder within the Infragistics/2013.2 folder. Incidently I have found that Infragistics needs to abandon the mapping plugin and go with a rewrite that is called viewModel. In my testing it is 100 times faster on data load.
From running some tests it seems the culprit is not the comparison itself but the fact that it finds each record to be different and therefore forces the grid to first delete all rows and then create every one coming from the new observable separately. I'll have to see what can be done in our KO integration about such cases, however, you can solve your issue by removing the grid's binding prior to reloading the model and then rebinding it. Attached you'll find a sample which achieves that (it doesn't really call for any data but rather just maps the same array).
I hope this helps! Please, let me know if you have any other questions or concerns!
Thank you, Stamen! Your example allowed me to understand how to work with it in MVC. In my situation I have one table in the model that feeds the igGrid, and another that feeds several textboxes. The only way could figure out how to bind the grid and the textboxes is to use ko.applyBindings(model) to bind everything, then drop the igGrid bindings, then reapply the igGrid bindings. Then after a json response, I drop the igGrid bindings, refresh the model and again, and reapply the binding to the igGrid.
Is there a cleaner way to bind the textboxes in my scenario? I spent several hours attempting to bind the textboxes by selecting them all with jquery and using applyBindingToNode in order to be more specific and keep from cleaning the grid bindings on document ready, but I could not get it to work that way. Here is my working version using the complex way:
Inside of document.ready - model = ko.mapping.fromJS(datasource); gridOpts.dataSource = model.Table2; // use table #2 for the igGrid ko.applyBindings(model); // necessary to bind the textboxes to table#1 ko.cleanNode($("#myGrid")[0]); ko.applyBindingsToNode($("#myGrid"), { igGrid: gridOpts }, model);
After Ajax response -ko.cleanNode($("#myGrid")[0]); ko.mapping.fromJS(result, model); // necessary to refresh model ko.applyBindingsToNode($("#myGrid")[0], { igGrid: gridOpts }, model);
Again, this does work. It's just a little wasteful and not very target specific.
In my original sample, I avoided adding the data-bind attribute to the grid's element initially so that the grid options were not passed around redundantly. You could however do that to save yourself from having to first bind the whole model and then the grid separately on the initial load of the page. The other solution is to stringify the gridOpts object and add the attribute dynamically before calling ko.applyBindings(model).
As for the issue with Paging, I added Paging without any options to my sample and it worked without issues. Do you use some specific configuration which I am not aware of?