1

I've seen similar topics about it, but none of them using exactly the same structure as me.

I am using multiple view models and I deal with it by creating a MasterModel function which later on I pass as an argument to applyBindings.

Basically something like this:

var MasterModel = function(){
    this.user = new UserViewModel();
    this.department = new DepartmentViewModel();
}

ko.applyBindings(MasterModel);

Now, I would like to be able to access from Javascript to a function inside one of my view models and I'm having troubles with it.

I managed to call the viewmodel function if I change the applyBindings to this:

var mm = new MasterModel();
ko.applyBindings(mm);

mm.user.sayHi();

But then I found out things like the following stop working:

<ul data-bind="foreach: department.list()">
     <li data-bind="text: department.getDemo($data)"></li>
</ul>

Message: department is not defined

Reproduction online

And as you can see here, it works perfectly when using ko.applyBindings(MasterModel);

Any solution for this?

3
  • to make view cleaner use with in such cases . very helpful
    – super cool
    Commented Jul 15, 2015 at 11:58
  • That doesn't solve much when you are inside nested elements like foreach
    – Alvaro
    Commented Jul 15, 2015 at 12:14
  • humm i believe you misunderstood what i am saying . check this jsfiddle.net/qWmat/111 . i am just trying to say use with not to replace in place of foreach . cheers
    – super cool
    Commented Jul 15, 2015 at 12:19

2 Answers 2

2

You need to point Knockout in the right direction in order to use department:

<li data-bind="text: $root.department.getDemo($data)"></li>

When you're inside a foreach loop, the scope is the item you're currently iterating on, and this item (obviously) doesn't have the department property.

You need to use $root to tell Knockout that it's the department defined on the root view-model you're referring to.

See Fiddle and Documentation

4
  • What about $parent? Why can't I use it?
    – Alvaro
    Commented Jul 15, 2015 at 12:12
  • In your particular case, you can use $parent as well. But, if you'll ever refactor your model to have more than one level of nesting $parent would break. You better use $root since you already know it's defined at the root of your view-model.
    – haim770
    Commented Jul 15, 2015 at 12:14
  • The bad thing of it is that it starts to look very verbose. The $parent doesn't work at all btw: jsfiddle.net/imac/qWmat/112
    – Alvaro
    Commented Jul 15, 2015 at 13:56
  • @Alvaro $parent will work check the comment to you post . cheers
    – super cool
    Commented Jul 15, 2015 at 14:43
1

Inside the foreach, you don't have direct access to department because foreach introduces its own binding context. You can use $root or $parent to access your MasterModel:

<ul data-bind="foreach: department.list()">
   <li data-bind="text: $parent.department.getDemo($data)"></li>
</ul>

http://jsfiddle.net/qWmat/109/

A binding context is an object that holds data that you can reference from your bindings. While applying bindings, Knockout automatically creates and manages a hierarchy of binding contexts. The root level of the hierarchy refers to the viewModel parameter you supplied to ko.applyBindings(viewModel). Then, each time you use a control flow binding such as with or foreach, that creates a child binding context that refers to the nested view model data.

Read more

2
  • I don't understand why you have to use $parent.department.getDemo($data) instead of just $parent.getDemo($data) as you are already inside a department loop.
    – Alvaro
    Commented Jul 15, 2015 at 12:02
  • You're not inside a department loop, you're looping over the list.
    – sroes
    Commented Jul 15, 2015 at 12:16

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