How to exchange value between two viewmodels in kn

2019-07-29 11:41发布

问题:

Hi i have two view models and i want to transfer a value between them. here is js fiddle

`http://jsfiddle.net/sohimohit/e84u8L85/`

i want when a user click on show another div button then corresponding item name should be display on another div . means i want to show one viewmodel value into another. secondly when a user click on show another div button another div appears i want an option of cancel so that user can go back to firstdiv. how can i achieve this.

回答1:

You can use global variables container1VM and container2VM for it.
E.g. call of

 container1VM.isVisible(!container1VM.isVisible());
 container2VM.isVisible(!container2VM.isVisible());  

will make visible container - invisible.

JSFiddle DEMO

Code:

HTML:

   <div id="container1">


       <div data-bind="visible: !isVisible()">
        <ul >
            <li >Container1 item</li>
            <!-- ko foreach: myItems -->
            <li>Item <span data-bind="text: $data"></span></li>
            <button data-bind="click:$root.showDiv">show another div</button>
            <!-- /ko -->
        </ul>

       </div>
    </div>
     <div id="container2" data-bind="visible:isVisible">
        <ul>
            <li >Container2 item</li>
            <!-- ko foreach: myItems -->
                <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
         <button data-bind="click:$root.cancel">cancel</button> 
    </div>   

Javascript:

function Container1ViewModel()
{
    var self = this;
    self.isVisible = ko.observable(false);
    self.showDiv = changeVisibility;
    self.myItems = ko.observableArray();
    self.myItems.push("ABC");
    self.myItems.push("CDE");

} 
function Container2ViewModel() {
    var self = this;
    self.isVisible = ko.observable();
    self.myItems = ko.observableArray();
    self.myItems.push("XYZ");
    self.myItems.push("PQR");
    self.cancel = changeVisibility;
}

function changeVisibility()
{
   container1VM.isVisible(!container1VM.isVisible());
   container2VM.isVisible(!container2VM.isVisible());
}

var container1VM = new Container1ViewModel();;
var container2VM = new Container2ViewModel();;

ko.applyBindings(container1VM, document.getElementById("container1"));

ko.applyBindings(container2VM, document.getElementById("container2"));


回答2:

Also consider using Knockout Postbox by the excellent Ryan Niemeyer: https://github.com/rniemeyer/knockout-postbox

You could use syncWith to update an observable controlling visibility. That way both viewmodels don't need to know about each other and you're not hard coding references to your viewmodels.

syncWith - syncWith(topic, [initializeWithLatestValue], [skipInitialPublish], [equalityComparer])

The syncWith function tells an observable to both subscribe and publish on a topic. This allows observables in two different view models to stay in sync with each other without having direct knowledge of its counterpart.

//subscribe to and publish on a topic
this.value = ko.observable(value).syncWith("mytopic");

//subscribe to and publish on a topic and use the last published value to initialize the     observable
this.value = ko.observable().syncWith("mytopic", true);

//subscribe to and publish on a topic, but do not publish out the observable's value initially
this.value = ko.observable(value).syncWith("mytopic", false, true);

//subscribe to and publish on a topic, but only publish when the comparer function returns false
var comparer = function(newValue, oldValue) {
    return newValue < oldValue;
};

this.value = ko.observable(value).syncWith("mytopic", false, false, comparer);