Brian Triplett
Brian Triplett

Reputation: 3532

$parent binding not required in template

Example at https://jsfiddle.net/btriplett/y3p8cdby/2/

I'm experiencing some confusing behavior with the $parent tag in knockout. I was experimenting with contextually removing items in a list and was expecting to have to use the $parent tag to access the parent viewmodel's remove function (see below).

Here is the markup:

<ul data-bind="foreach: list">
    <li>
        <div>
            <span data-bind="text: name"></span>
            <button data-bind="click: $parent.remove">Remove</button>
        </div>
    </li>
</ul>

Here is the viewmodel

var data = [ {name: "Bob"}, {name:"Joe"}, {name: "John"}];

function viewModel() {
    var self = this;

    self.list = ko.observableArray(data);

    self.remove = function(item){
        self.list.remove(item);
    };
};

ko.applyBindings(viewModel());

However, this doesn't work. I get (in Chrome with knockout 3.0).

Uncaught TypeError: Unable to process binding "foreach: function (){return list }"
Message: Unable to process binding "click: function (){return $parent.remove }"
Message: Cannot read property 'remove' of undefined

but if I remove the $parent it works! This is not at all what I expected because the context of the list item is the item and not the viewmodel. Does anyone know why this is?

Upvotes: 0

Views: 45

Answers (2)

CrimsonChris
CrimsonChris

Reputation: 4641

Here's an example of how you can make your classes not fail when you forget to call new on them.

function ViewModel(params) {
    if (!(this instanceof ViewModel)) {
        return new ViewModel(params);
    }

    ...
}

Upvotes: 0

Roy J
Roy J

Reputation: 43881

viewModel is a constructor that should be called with new. Or (I would recommend) change the first line of it to

var self = {};

and call it as you have here.

Upvotes: 1

Related Questions