Accessing a parent viewmodel from a checkbox change within a child view

I have the following view, which render 2 copies of a child view, as you can see they're bound to 2 properties on a parent viewmodel.

<div class="row">
    <div class="col-sm-4" data-bind="with: primaryPerson">
        <h5 data-bind="visible: $root.isMirror">You</h5>
         @{Html.RenderPartial("_PropertyQuestionnaire");}
    </div>
    <div class="col-sm-4" data-bind="visible: isMirror, with: secondaryPerson">
        <h5 data-bind="visible: $root.isMirror">Your partner</h5>
        @{Html.RenderPartial("_PropertyQuestionnaire");}
     </div>
</div>

That repeated view is very simple, just 2 checkboxes bound to properties on a child viewmodel

<div class="checkbox">
    <label>
        <input type="checkbox" data-bind="checked: ownsMainHome">
        Main home
    </label>
</div>
<div class="checkbox">
    <label>
        <input type="checkbox" data-bind="checked: ownsOtherProperty">
        Other properties
    </label>
</div>

Here is the simplified viewmodels used above, first the parent, bound to the top view

function MainViewModel(){
    var self = this;
    self.primaryPerson = new PersonViewModel();
    self.secondaryPerson = new PersonViewModel();

    self.mainHomeChanged = function(){
        // My question (i'll get to it!!) Is about this method
    }
}

And here is the PersonViewModel bound to both of the repeated views above

function PersonViewModel(){
    var self = this;

    self.ownsMainHome = ko.observable(false);
    self.ownsOtherProperty = ko.observable(false);
}

The observable ownsMainHome is bound to one of the 2 checkboxes in the repeated views. When either of them changes I need to call the function mainHomeChanged in the parent view model.

I have read about knockout extenders and custom bindings but im not sure that im just overcomplicating this.

I tried extending the observable for ownsMainHome on the child viewmodels:

self.ownsMainHome = ko.observable(false).extend({addHomeAddress:true});

and

ko.extenders.addHomeAddress = function (target, option) {
    target.subscribe(function (newValue) {
        console.log(target);
        console.log(this);
    });
    return target;    
}

The console.log being my attempt to locate the bindingcontext! I also tried

 ko.extenders.addHomeAddress = function (target, option) {
    target.subscribe(function (newValue) {
        console.log(ko.contextFor(target));
    });
    return target;    
}

But of course target is an object representing the subscribers, not the binding.

So I'm a bit stuck.


There are lots of ways to solve this. Here is three solution:

You can use the event binding to subscribe on the change event and call your method:

<input type="checkbox" data-bind="checked: ownsMainHome, 
                                  event: { change: $parent.mainHomeChanged }" />

Demo JSFiddle.

You can pass in the MainViewModel to your PersonViewModel :

self.mainHomeChanged = function(){
    alert('mainHomeChanged');
}

self.primaryPerson = new PersonViewModel(self);
self.secondaryPerson = new PersonViewModel(self);

And in your PersonViewModel

function PersonViewModel(parent){
    var self = this;

    self.ownsMainHome = ko.observable(false);
    self.ownsOtherProperty = ko.observable(false);

    self.ownsMainHome.subscribe(parent.mainHomeChanged);
}

Demo JSFiddle.

Or you can directly subscribe from your MainViewModel :

self.primaryPerson = new PersonViewModel();
self.secondaryPerson = new PersonViewModel();

self.mainHomeChanged = function(){
    alert('mainHomeChanged');
}

self.primaryPerson.ownsMainHome.subscribe(self.mainHomeChanged);
self.secondaryPerson.ownsMainHome.subscribe(self.mainHomeChanged);

Demo JSFiddle.

链接地址: http://www.djcxy.com/p/50144.html

上一篇: 清除可观察物淘汰赛中的所有值

下一篇: 在复选框中访问父视图模型会在子视图中更改