Maurizio In denmark
Maurizio In denmark

Reputation: 4284

Two observableArrays don't work together in the same page with a nested viewModel

I have this viewModel:

ViewModel

var sitesTableModel = [
{
   nameCol: "nameCol-1",
   pagesCol: "editorCol-1",
},
{
    nameCol: "nameCol-2",
    pagesCol: "pagesCol-2",
}];

var pagesTableModel = [
{
   lastCol: "lastCol-1",
   editedCol: "editedCol-1",
},
{
    lastCol: "lastCol-2",
    editedCol: "editedCol-2",
}];


var viewModel = {
    sitesTable: ko.observableArray(sitesTableModel),
    pagesTable: ko.observableArray(pagesTableModel),
};

then I call a webservice in this way:

Ajax Call

ajaxService = (function () {
var ajaxGetJson = function (method, request, callback, service) {
    $.ajax({
        url: "http://localhost:2880/Whatever.svc/Method",
        type: "GET",
        data: request,
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        success: function (result, statusMsg, status)
        {
            callback(result, statusMsg, status, request);
        },
        error: ServiceFailed 
    }).always(function () {
        ko.applyBindings(viewModel); 
        });
}
return {
    ajaxGetJson: ajaxGetJson,
};
})();

and map the result in this way:

Mapping

function ModelTableSitesMapper(result, statusMsg, status, request) {

    var itemRow = [];

    //sitesTableModel
    result.forEach(function (entry) {
        itemRow.push({
            nameCol: entry.Title,
            pagesCol: entry.Pages,
        })
    });

    viewModel.sitesTable = ko.observableArray(itemRow);

};

And the same for the other array.

Now here is my data binding:

Data Binding

    <table id="tableDocs">  
        <tbody data-bind="foreach: documentsTable" >
        <tr>
            <td data-bind="text: nameCol">Simon Werner Hansen</td>
            <td data-bind="text: pagesCol">swh002</td>
        </tr>
        </tbody>
    </table>


    <table id="tableSites">  
        <tbody data-bind="foreach: documentsTable" >
        <tr>
            <td data-bind="text: lastCol">Simon Werner Hansen</td>
            <td data-bind="text: editedCol">swh002</td>
        </tr>
        </tbody>
    </table>

If I comment one of the two the other work fine, but if they are together on the same page the table is just empty, no errors or nothing.

Aomething to do with the context of the model?

Upvotes: 0

Views: 253

Answers (2)

Maurizio In denmark
Maurizio In denmark

Reputation: 4284

I found the problem.

I was applying the binding ko.applyBinding on the .always function of the ajax call, but because I was calling the service twice for 2 different reasons the binding was applied TWICE.

I donøt know why but for some reason that prevented the 2 different observableArrays to work together in the same model. So this is a solution but it does not explain why this happended.

I just moved the binding outside the function just after I create my model.

Upvotes: 0

Ryan Rahlf
Ryan Rahlf

Reputation: 1812

I notice in your mapping code you're doing

viewModel.sitesTable = ko.observableArray(itemRow);

and I'm wondering if you want

viewModel.sitesTable(itemRow);

Once you've created your knockout observable or observableArray during initialization, you'll want to be careful not to overwrite those with another new observableArray, particularly once you've called ko.applyBindings().

I think this is best shown with an example...

//Initialize my view model
var myOriginalObservable = ko.observableArray([initialValue]);

var viewModel = {
    modelProperty : myOriginalObservable
}

//Call applyBindings
ko.applyBindings(viewModel);

//In some other function, I reset viewModel.modelPropert = ko.observableArray()
var myNewObservable = ko.observableArray([newValue]);

viewModel.modelProperty = myNewObservable;

After the call to applyBindings, some other operation sets my viewModel's property to a new observable instead of just changing the values in the existing observable. The observable that I created in initialization (myOriginalObservable) is still there, and my UI is still bound to it, but I've lost my reference to it when I changed the object that viewModel.modelProperty pointed to (myNewObservable).

I think this may be the issue you're running in to.

Upvotes: 1

Related Questions