2

i have two view models and i want to pass value from one view model to another viewmodel. i have two viewmodels and two div i want to display another div on click of button which is present in div 1.

here is html code

   <div id="container1">
        <ul >
            <li >Container1 item</li>
            <!-- ko foreach: myItems -->
            <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
        <button data-bind="click:showDiv">show another div</button>
    </div>
     <div id="container2" data-bind="visible:show">
        <ul>
            <li >Container2 item</li>
            <!-- ko foreach: myItems -->
                <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div> 

and here is script

function Container1ViewModel()
{
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("ABC");
    self.myItems.push("CDE");

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

}


var container1VM;
var container2VM;

$(document).ready(function() {

    if ($.isEmptyObject(container1VM)) {
        container1VM = new Container1ViewModel();
        ko.applyBindings(container1VM, document.getElementById("container1"));
    }

    if ($.isEmptyObject(container2VM)) {
        container2VM = new Container2ViewModel();
        ko.applyBindings(container2VM, document.getElementById("container2"));
    }
});

how can i do it ?

user2142786
  • 1,484
  • 9
  • 41
  • 74

3 Answers3

6

You can make use of KO.postbox by the great @RyanNiemeyer

I introduced one variable in both the viewmodels each

In viewmodel 1 which will publish (shout) the changes once made :

self.isVisible = ko.observable(false).publishOn("showDiv");

in viewmodel 2 which will be listning to changes from viewmodel 1

self.isVisible = ko.observable(false).subscribeTo("showDiv");

Then I created one click method in first viewModel to toggle Show Div action (visible : true / false)

self.showDiv = function(){
     if(self.isVisible())
         self.isVisible(false);
    else
        self.isVisible(true);
}

Changed visible binding from your existing markup to this :

<div id="container2" data-bind="visible:isVisible">

It now publish changes made in first viewmodel to second viewmodel. This is called pub-sub mechanism. Read more on : https://github.com/rniemeyer/knockout-postbox

Fiddle here : http://jsfiddle.net/rahulrulez/0454h205/1/

Rahul Patil
  • 5,656
  • 6
  • 37
  • 65
  • Here i am sharing my fiddle with you. i have branch area and every brach area has some branches . so i want on click of showbranches i can hide the div of showbrancharea and show the branches div and there is a option of cancel so that on cancel we can go back to branch area i.e hide branches and show brancharea – user2142786 Aug 18 '14 at 06:30
  • i am not able to do it for eachfield yet it is working if i use it by keeping out of div i need it on click of every field. i even use $root.brancharea but it doesn't work. any other way to do this ? – user2142786 Aug 18 '14 at 06:41
  • Can you post jsfiddle? – Rahul Patil Aug 18 '14 at 07:09
  • Here is js fiddle http://jsfiddle.net/sohimohit/43zkoszu/ now i am able to show and hide the div but when i am trying for an option of cancel this operation using cancelField it is not working one thing more i want to ask if i want to send branchid from brancharea viewmodel to branch viewmodel on click of showfield . how can i acheive this. – user2142786 Aug 18 '14 at 07:21
  • What is `cancelField` supposed to do? – Rahul Patil Aug 18 '14 at 08:39
  • it has to take me back at brancharea fields – user2142786 Aug 18 '14 at 08:41
  • do u find any solution regarding this ? – user2142786 Aug 18 '14 at 13:27
  • No problem buddy.. and can you verify is it my right approach to do this task.. hope you understand my scenario.. – user2142786 Aug 18 '14 at 13:37
  • If you can explain me what exactly you want to achieve, I can help you with the code. Detailed explanation would be great. :-) write it here http://notes.io/ and click on short icon, it will generate shortlink, share it with me.. – Rahul Patil Aug 18 '14 at 13:52
  • i post another question regarding same requirement http://stackoverflow.com/questions/25376632/how-to-exchange-value-between-two-viewmodels-in-knockout-js – user2142786 Aug 19 '14 at 06:03
0

rjdmello already pointed you to AmplifyJS. Amplify offers (amongst other things) a publish/subscribe mechanism. Pub/sub is a good way to facilitate communication between modules that are loosely coupled. One module subscribes to a topic, and any other module can publish a message with that topic (and any data you'd like to send along). Once a topic is published, all subscribers will be notified.

Some code demonstrating Amplify in this case:

Container1ViewModel.prototype.showDiv = function (event) {
    amplify.publish('show-div', { clickedButton: event.target });
}

function Container2ViewModel() {
    var onShowDiv = function (data) {
        if ($(data.clickedButton).hasClass('.enabled')) {
            // Show me teh div!!
            this.myItems.push("ABC");
        }
    };
    this.myItems = ko.observableArray();
    this.myItems.push("XYZ");
    this.myItems.push("PQR");

    amplify.subscribe('show-div', this, onShowDiv, 1);
}

Using pub/sub to keep modules loosely coupled is generally very good practise (although you shouldn't overdo it because it will become harder to track how modules cooperate).

And while we are on the practise of good practise, don't use self = this, use Function.prototype.bind instead. http://www.smashingmagazine.com/2014/01/23/understanding-javascript-function-prototype-bind/

Hans Roerdinkholder
  • 3,000
  • 1
  • 20
  • 30
0

For this you can follow these

Viewmodels

function vm1(parent){
    var self = this
    self.parent = ko.observable(parent)
    .
    .
    .

    self.myfunction(data){
        self.parent().pageParameters(data)
    }
}
function vm2(parent){
    var self = this
    self.parent = ko.observable(parent)
    .
    .
    .

    self.myotherfunction(){
        var othervmdata = self.parent().pageParameters()
        .
        .
    }
}

function vm(){
    var self = this

    self.vm1 = ko.observable();
    self.vm2 = ko.observable();

    self.pageParameters = ko.observable

    self.loadData = function(){
        self.vm1(new vm1(this))
        self.vm2(new vm1(this))
    }
}

View

<div data-bind="with:vm1">
.
.
.
</div>
<div data-bind="with:vm2">
.
.
.
</div>  

This way when you bind myfunction to click binding parent model will have the data you want to pass then on the other view model you can access parent property pageParameters.

For more details see my post.

Muhammad Raheel
  • 19,823
  • 7
  • 67
  • 103
  • HI Raheel, Here is js fiddle jsfiddle.net/sohimohit/43zkoszu/04 now i am able to show and hide the div by clicking on showfield but when i am trying for an option of cancel this operation using cancelField it is not working one thing more i want to ask if i want to send branchid from brancharea viewmodel to branch viewmodel on click of showfield . how can i acheive this. – user2142786 Aug 18 '14 at 08:12