4
votes

When the page loads I get the data by calling getGeneJSONData() and when I do a database udpate i call the same method to load the new data and I get the error "You cannot apply bindings multiple times to the same element"

Here's the code snips

    var geneViewModel = null;

    var Gene = function (data) {
    data = data || {};

    var self = this;
    self.geneValue = data.GeneValue;
    self.geneCode = ko.protectedObservable(data.GeneCode);
    self.geneName = ko.protectedObservable(data.GeneName);
    self.geneComments = ko.protectedObservable(data.GeneComments);

};

var ViewModel = function (items) {
    var self = this;
    var newGene = { "geneValue": "", "geneCode": ko.protectedObservable(null), "geneName": ko.protectedObservable(null), "geneComments": ko.protectedObservable(null) };

    self.genes = ko.observableArray(ko.utils.arrayMap(items, function (data) {
        return new Gene(data);
    }));

self.updateGene = function (gene) {
     getGeneJSONData();
}
}

    function getGeneJSONData() {
    $.ajax({
        type: "GET",
        url: urlPath + '/GetGenes',
        dataType: "json"
    }).done(function (result) {
        if (result) {
            if (result.Success) {
                var geneData = result.Data;

                    geneViewModel = new ViewModel(geneData);
                    ko.applyBindings(geneViewModel);

            }

        }
    });
};

    $(document).ready(function ($) {

    getGeneJSONData();

});

I am not sure why I'm getting this error on the data reload. Do I have to remove the bindings before applying them again?

2
You only need to apply bindings once. Instead of creating a new ViewModel for AJAX request, just use the same ViewModel and update its properties. - Bradley Trager
because every time you make ajax request, you are calling applybinding don't do that. - Akhlesh

2 Answers

2
votes

You only need to apply bindings once. Instead of creating a new ViewModel for AJAX request, just use the same ViewModel and update its properties.

I would suggest that you do this by applying your bindings in your document ready function and passing your ViewModel to your update function. Here is how I would do it:

var ViewModel = function(items) {
    var self = this;
    var newGene = {
        "geneValue": "",
        "geneCode": ko.protectedObservable(null),
        "geneName": ko.protectedObservable(null),
        "geneComments": ko.protectedObservable(null)
    };

    self.genes = ko.observableArray(ko.utils.arrayMap(items, function(data) {
        return new Gene(data);
    }));

    //pass in view model here
    self.updateGene = function(gene) {
        getGeneJSONData(self);
    }
}

    function getGeneJSONData(viewModel) {
        $.ajax({
            type: "GET",
            url: urlPath + '/GetGenes',
            dataType: "json"
        }).done(function(result) {
            if (result) {
                if (result.Success) {
                    var geneData = result.Data;
                    viewModel.genes = result.Data

                }

            }
        });
    };

$(document).ready(function($) {
    //apply bindings here
    ko.applyBindings(geneViewModel);
    getGeneJSONData();
});
2
votes

You do not need to call ko.applyBindings() repeatedly to refresh your view. Any change in your ViewModel is automatically updated in view because of KnockoutJS's automatic dependency tracking. In your case, ko.applyBindings() is called whenever the AJAX call is completed. Build a one time solution like for the first time you get the data from the AJAX call, call ko.applyBindings() with your viewModel and in subsequent calls, just update the viewmodel.