knockout.jsknockout-mapping-plugin

copy only writable items from Knockout ViewModel


There are several items includes functions and observable variables in my ViewModel But at the time of posting, I need only the writable items.

var viewModel = {
    firstName: ko.observable().extend({ minLength: 2, maxLength: 10 }),
    lastName: ko.observable().extend({ required: true }),
    emailAddress: ko.observable(),
    age: ko.observable().extend({ min: 1, max: 100 }),
    options: ['News', 'Music'],
    subscription: ko.observable().extend({ required: true }),
    password: ko.observable(),
    submit: function () {
        var model = cloneObservable(viewModel);
    },
    reset: function () {
    }
};

ko.applyBindings(viewModel);

clone viewModel:

 function cloneObservable(viewModel) {
    var model = ko.observableArray([]);
    Object.keys(viewModel).forEach(function (name) {
        if (ko.isWritableObservable(viewModel[name])) {
            model.push(viewModel[name]);
        }
    })
    return ko.mapping.fromJS(ko.toJS(model));
 }

viewModel[name] does not return Observable variable.


Solution

  • You have to get the instance of the viewModel and use that in CloneObservable function.

    I removed ko.mapping.fromJS from the function to illustrate that the values are coming correctly.

    function cloneObservable(viewModel) {
      var model = ko.observableArray([]);
      Object.keys(viewModel).forEach(function (name) {
          if (ko.isWritableObservable(viewModel[name])) {
              model.push(viewModel[name]);
          }
      })
      return ko.toJS(model);
    }
    
    
    var viewModel = function(){
      var self = this;
      self.firstName = ko.observable('sal').extend({ minLength: 2, maxLength: 10 });
      self.lastName = ko.observable('mon').extend({ required: true });
      self.emailAddress = ko.observable('email');
      self.age = ko.observable(21).extend({ min: 1, max: 100 });
      self.options = ['News', 'Music'];
      self.subscription = ko.observable('yes').extend({ required: true });
      self.password = ko.observable('secret');
      self.submit = function(){
         
      };
      
    };
    
    var viewModelInstance = new viewModel();
    
    ko.applyBindings(viewModelInstance);
    
    
    console.log(cloneObservable(viewModelInstance));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>