Search code examples
javascriptknockout.jsknockout-mapping-plugin

Using Knockoutjs Mapping Plugin inside viewmodel constructor


I am trying to use the mapping plugin inside the constructor so I can easily add other functions to the constructor and have the observable items automatically created from the mapping plugin. Here is the code that I currently have but it is neither mapping the observable variables that I provide it or including the 'save' function in the end viewmodel. Is there a better way to do this?

function ViewModel(model){
        var self = this;

        self = ko.mapping.fromJS(model);

        self.save = function() {
            var data = ko.toJSON(self);
            $.post("/Licensing/edit", data, function(returnedData) {
                // This callback is executed if the post was successful
            });
        }

    };

    var vm = new ViewModel(model);
    ko.applyBindings(vm);

Solution

  • Your code is not working because ko.mapping.fromJS(model); returns a new object what you assign to your self local variable what you extend with the save function.

    However this new object is not returned from your constructor function so you will end with with an empty object because not the originally passed in this is modified.

    You can fix this with returning self from your constructor:

    function ViewModel(model){
        var self = this;
    
        self = ko.mapping.fromJS(model);
    
        self.save = function() {
            var data = ko.toJSON(self);
            $.post("/Licensing/edit", data, function(returnedData) {
                // This callback is executed if the post was successful
            });
        }
    
        return self;
    };
    

    Or you can tell the mapping plugin to don't create a new object just use the currently created one with passing self as the third argument:

    function ViewModel(model){
        var self = this;
    
        ko.mapping.fromJS(model, {}, self);
    
        self.save = function() {
            var data = ko.toJSON(self);
            $.post("/Licensing/edit", data, function(returnedData) {
                // This callback is executed if the post was successful
            });
        }
    
    };