rubin
rubin

Reputation: 707

$parent binding doesnt work as i want to in knockout why?

I have a problem with the $parent in javascript knockouts.

If i have model:

        var Person = function () {

        var self = this;

        self.person_Id = ko.observable(); 
        self.firstName = ko.observable(); 
        self.lastName = ko.observable(); 
        self.age = ko.observable(); 
        self.role = ko.observable(); 

        self.init = function (data) {

            self.person_Id(data.person_Id);
            self.firstName(data.firstName);
            self.lastName(data.lastName);
            self.age(data.age);
            self.role(data.role);
        };

    };

and the collection

        var PersonCollection = function () {

        var self = this;

        self.ItemToEditOrToAdd = ko.observable(new Person());  

        self.persons = ko.observableArray();

        self.AddItem = function (item) {

            self.persons.push(item);


        };

    };

and the html

                <div id="new" data-bind="with: PersonCollectionInstance.ItemToEditOrToAdd">

                <p>Firstname: <input type="text" data-bind="value: firstName"/></p>
                <p>Lastname: <input type="text" data-bind="value: lastName"/></p>
                <p>Age: <input type="text" data-bind="value: age"/></p>
                <p>Role: <input type="text" data-bind="value: role"/></p>
                <button data-bind="click: $parent.PersonCollectionInstance.AddItem">Add new</button>

            </div>

If you look at the html, the natural way to access AddItem is to write

<button data-bind="click: $parent.AddItem">Add new</button>

This doesnt work, because the $parent binding gets me to my AppVM that is my all mighty view model, instead of going back to my PersonCollectionInstance.

Thats why i need to do it like this:

 <button data-bind="click: $parent.PersonCollectionInstance.AddItem">Add new</button>

Can anyone explain to me why $parent gets me back to my all mighty viewmodel instead of the PersonCollectionInstance where my AddItem is?

Upvotes: 3

Views: 1348

Answers (1)

nemesv
nemesv

Reputation: 139758

You need to write data-bind="click: $parent.PersonCollectionInstance.AddItem" because you have defined your with like this:

data-bind="with: PersonCollectionInstance.ItemToEditOrToAdd"`

So you have stepped down two levels in your with binding because you have accessed a nested property. However the $parent is still pointing to your main view model because knockout isn`t able track your nested property and it doesn't create the nested contexts for you.

So can achieve the desired outcome with using two with:

<div id="new" data-bind="with: PersonCollectionInstance">
  <!-- ko with: ItemToEditOrToAdd -->
    <p>Firstname: <input type="text" data-bind="value: firstName"/></p>
    <p>Lastname: <input type="text" data-bind="value: lastName"/></p>
    <p>Age: <input type="text" data-bind="value: age"/></p>
    <p>Role: <input type="text" data-bind="value: role"/></p>
    <button data-bind="click: $parent.AddItem">Add new</button>
  <!-- /ko -->
</div>

And if you anyway using two with you can put your button "outside":

<div id="new" data-bind="with: PersonCollectionInstance">
  <!-- ko with: ItemToEditOrToAdd -->
    <p>Firstname: <input type="text" data-bind="value: firstName"/></p>
    <p>Lastname: <input type="text" data-bind="value: lastName"/></p>
    <p>Age: <input type="text" data-bind="value: age"/></p>
    <p>Role: <input type="text" data-bind="value: role"/></p>       
  <!-- /ko -->
  <button data-bind="click: AddItem">Add new</button>
</div>

Upvotes: 5

Related Questions