dmathisen
dmathisen

Reputation: 2342

KnockoutJS multiple view models and 'breaking out' of one

So I'm working with multiple view models using KnockoutJS, like this:

function firstViewModel() {
    var self = this;
    self.dataArray = ko.observableArray([
        { title: "title1", theData: "data1" },
        { title: "title2", theData: "data2" },
        { title: "title3", theData: "data3" },
    ]);
};

function secondViewModel() {
    var self = this;
    self.addData = function() {
        firstViewModel.dataArray.push({ title: "newTitle", theData: "newData" });
        // trying to trigger dataArray in firstViewModel, doesn't work
    }
};

ko.applyBindings(new firstViewModel(), document.getElementById('first'));
ko.applyBindings(new secondViewModel(), document.getElementById('second'));

Then something like:

<div id="first" data-bind="with: dataArray">
    <ul data-bind="foreach: $data">
        <li data-bind="text: theData"></li>
    </ul>
</div>
<div id="second">
    <button data-bind="click: addData">add</button>
</div>

The reason it's structured like this is because I have a 3rd view model and the elements overlap in the DOM. I couldn't figure out how to get this to work either.

Is there any way to keep the structure and reference firstViewModel inside of secondViewModel? firstViewModel.theData.push("newData"); clearly doesn't work, but I thought I'd include it to further clarify what I'm looking to do.

I'm brand new to KO - sorry if it's a stupid question.

EDIT: Looks like I got it!

If I remove 'self' from the firstViewModel it works...

dataArray = ko.observableArray([
    { title: "title1", theData: "data1" },
    { title: "title2", theData: "data2" }
]);

then

self.addData = function() {
    dataArray.push({ title: "newTitle", theData: "newData" });
}

I don't know yet if there are consequences of removing the 'self', but it's working so far.

Upvotes: 1

Views: 443

Answers (2)

Paul Manzotti
Paul Manzotti

Reputation: 5147

Personally, I prefer to keep my models de-coupled, and use a publish/subscribe pattern to allow them to talk to each other. See my answer to Variable Dependency with knockoutJS

In addition, if you do want to go down that road, you can also look at knockout postbox to accomplish the same thing.

Upvotes: 1

sroes
sroes

Reputation: 15053

You could pass a reference of the first viewmodel:

function firstViewModel() {
    var self = this;
    self.dataArray = ko.observableArray([
        { title: "title1", theData: "data1" },
        { title: "title2", theData: "data2" },
        { title: "title3", theData: "data3" },
    ]);
};

function secondViewModel(firstViewModel) {
    var self = this;
    self.addData = function() {
        firstViewModel.dataArray.push({ title: "newTitle", theData: "newData" }); // doesn't work
    }
};

var firstVm = new firstViewModel();
var secondVm = new secondViewModel(firstVm);
ko.applyBindings(firstVm, document.getElementById('first'));
ko.applyBindings(secondVm, document.getElementById('second'));

Upvotes: 0

Related Questions