1

I'm trying to use multiple view models as suggested in the documentation and in this other answer.

I'm getting an error in the console complaining about a variable not being defined:

Uncaught ReferenceError: Unable to process binding "foreach: function (){return seals }" Message: seals is not defined

Reproduction online

HTML

<!-- ko foreach: seals -->
<div class="form-group">
    <label for="seal" class="col-xs-2 control-label" data-bind="text: 'Seal ' + name"></label>
    <div class="col-xs-8">
        <input type="text" class="form-control" data-bind="attr: {name: 'seal' + formName}" />
    </div>
</div>
<!-- /ko -->

JS

ko.applyBindings(demo, document.body);
ko.applyBindings(addEquipmentModel, document.getElementById('whatever'));
Community
  • 1
  • 1
Alvaro
  • 40,778
  • 30
  • 164
  • 336

2 Answers2

2

The problem is here:

ko.applyBindings(demo, document.body);

You are applying a model to document.body, so it's going to try and parse and bind the whole document. When it gets to the part with:

<!-- ko foreach: seals -->

You get an error because the demo model doesn't have a seals property.

In practice, you don't want the elements that you are binding to overlap. In other words, don't bind one model to a child element of an element that is bound to another model. They should be siblings, or cousins. Not direct descendants.

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
  • Yeah I see make sense. A question aside. How many models would you recommend creating in a site? I'm using a different one for a menu popup, but not sure if the separation will be even necessary and the advantages of it. Not quite clear in the docs. Like, would it make sense to have one for the header, other for the body and others for standalone elements? – Alvaro Jun 30 '15 at 16:01
  • @Alvaro: Bit of a "how long is a piece of string?" question. The answer is "it depends". Personally, I prefer to have a single model which contains as many sub-models as I want / need / makes sense rather than try to bind different models to different parts of the DOM. Makes it easier if later on those parts need to get mixed up. – Matt Burland Jun 30 '15 at 16:03
  • Right I see. Thanks for it. – Alvaro Jun 30 '15 at 16:06
  • In that case you have to always use `with` before data-bind, dont you? – Alvaro Jun 30 '15 at 16:11
  • Is it possible to do int he same binding: `with: addEquipment, click: clearSeals`? – Alvaro Jun 30 '15 at 16:23
  • 1
    @Alvaro: You can use `with` for different sections binding to the view model you are using for that particular section. Or you can just fully qualify your properties, for example `foreach: mySubModel.myProperty`. Or you can mix both approaches as needed. Also don't forget `$parent` if you need to navigate back up a level when you are in a `with` bound block. – Matt Burland Jun 30 '15 at 19:52
1

If you need several viewmodels nested in your view, or even in a child-parent relation, you should consider using Knockout components for that. Another possibility aside from that is to use apply(this) in your main viewmodel to the other viewmodels 'class' so your main viewmodel sort of inherits the functionality and properties of the referred model. This will, though, lead to problems if you have name concurrencies in your viewmodels.

connexo
  • 53,704
  • 14
  • 91
  • 128