5

In my specific example, there are several different widgets that have their own encapsulated ViewModel. I need a global Save button that saves each individual ViewModel. I can't seem to figure out how to call functions on the individual ViewModels.

Example - how can I call the Save function on each ViewModel: http://jsfiddle.net/sNSh2/4/

var ViewModel1 = function() {
    var self = this;
    self.firstName = ko.observable('');
    self.lastName = ko.observable('');

    self.firstName('John');
    self.lastName('Doe');

    self.Save = function () {
        alert(ko.toJSON(self));
    };
};
ko.applyBindings(new ViewModel1(), document.getElementById("person"));

var ViewModel2 = function() {
    var self = this;
    self.subscriptionLevel = ko.observable('');

    self.subscriptionLevel('premier');

    self.Save = function () {
        alert(ko.toJSON(self));
    };
};
ko.applyBindings(new ViewModel2(), document.getElementById("subscription"));

$('#save').on('click', function() {

});

3 Answers 3

15

I don't understand your problem, why not simply hold a reference of your model object?

$(function() {
  ...
  var m1 = new ViewModel1();
  ko.applyBindings(m1, document.getElementById("person"));

  ...
  var m2 = new ViewModel2();
  ko.applyBindings(m2, document.getElementById("subscription"));

  $('#save').on('click', function() {
    m1.Save();
    m2.Save();
  });
});

If you really have problem to get references of all model objects (maybe defined in isolated js files), ko provided way to get context object out from associated DOM object. You can still do this:

ko.contextFor(document.getElementById("person")).$data.Save();
ko.contextFor(document.getElementById("subscription")).$data.Save();
3
  • ko.contextFor is exactly what I was looking for. Thanks!
    – Mike Cole
    Commented Mar 19, 2014 at 14:15
  • ko.applyBindings() returns undefined in Knockout 3.2 and 3.3, making it impossible to hold a reference to the view model. Some examples from the official documentations are therefore broken. Any idea why?
    – CodeManX
    Commented Mar 10, 2015 at 10:50
  • @CoDEmanX, I don't understand your issue. Nobody uses the return value of ko.applyBindings(...). Please put a jsfiddle to show your code.
    – user1375096
    Commented Mar 10, 2015 at 22:34
1

Knockout has basic pub/sub functionality. try this on for size jsFiddle

var postbox = ko.observable();

var ViewModel1 = function() {
    var self = this;
    self.firstName = ko.observable('');
    self.lastName = ko.observable('');

    self.firstName('John');
    self.lastName('Doe');

    self.Save = function () {
        alert(ko.toJSON(self));
    };
    postbox.subscribe(function(newValue){
        self.Save();
    }, self, 'save');
};
ko.applyBindings(new ViewModel1(), document.getElementById("person"));

var ViewModel2 = function() {
    var self = this;
    self.subscriptionLevel = ko.observable('');

    self.subscriptionLevel('premier');

    self.Save = function () {
        alert(ko.toJSON(self));
    };

    postbox.subscribe(function(newValue){
        self.Save();
    }, self, 'save');
};
ko.applyBindings(new ViewModel2(), document.getElementById("subscription"));

$('#save').on('click', function() {
    postbox.notifySubscribers(null, "save");
});
1
  • Essentially the page has an all-encompassing view model, that has the postbox observable. Commented Mar 19, 2014 at 1:34
0

You just need to instantiate your ViewModel1 and ViewModel2 functions:

$('#save').on('click', function() {
   var vm1 = new ViewModel1(),
       vm2 = new ViewModel2();

   vm1.SayHi();
   vm2.SayHi();
});
1
  • Apologies, my example wasn't really capturing what I was trying to do. I updated my question. When I instantiate new versions of the ViewModels I lose the state of the existing ViewModels.
    – Mike Cole
    Commented Mar 18, 2014 at 21:42

Not the answer you're looking for? Browse other questions tagged or ask your own question.