Rippo
Rippo

Reputation: 22424

Bind multiple view models in KnockoutJs

I am trying to work out how I bind multiple models from a master model to different parts of my HTML mark up. The HTML part is:-

   <ul data-bind="foreach: { data: members}">
        <li>
            <span data-bind="text: MemberId"></span>
            <span data-bind="text: Name"></span>
            <span data-bind="text: SwagCompany"></span>
            <span data-bind="text: SwagThing"></span>
        </li>
    </ul>

<span data-bind="text: winner.Name"></span>

But can't work out how to bind the winner.Name, my model looks like this:-

var masterViewModel = {
   vmA : { ...},
   vmB : { ... }
}

ko.applyBindings({
      winner: ko.observable(masterViewModel.vmB),
      members: ko.observableArray(mappedData),
      ...
    }

Obviously I am misunderstanding how to applyBindings correctly. I have the following code as a plunker showing an example of what I am trying to do:-

<script>
$(function () {

    var masterViewModel = {
        vmA: function memberViewModel(data) {
            this.Id = data.MemberId;
            this.MemberId = ko.observable(data.MemberId);
            this.Name = ko.observable(data.Name);
            this.SwagCompany = ko.observable("");
            this.SwagThing = ko.observable("");
            this.Photo = ko.observable(data.Photo);
        },
        vmB: {
            Name: "Initial winner..."
        }
    };

    $.getJSON("/home/memberlist")
        .then(function (rawData) {
            return ko.utils.arrayMap(rawData, function (instanceData) {
                return new masterViewModel.vmA(instanceData);
            });
        })
        .done(function (mappedData) {
            doit(mappedData);
        });

    function doit(mappedData) {
        ko.applyBindings({
            winner: ko.observable(masterViewModel.vmB),
            members: ko.observableArray(mappedData),
            getNextWinner: function () {
                var members = this.members();
                var winner = this.winner();
                //console.log(ddd.Name());
                $.getJSON("/home/nextwinner")
                    .then(function (rawData) {
                        var nextWinner = ko.utils.arrayFirst(members, function (member) {
                            return member.Id === rawData.Winner.MemberId;
                        });
                        nextWinner.SwagThing(rawData.WonSwag.Thing);
                        nextWinner.SwagCompany(rawData.WonSwag.Company);
                        winner.Name(rawData.Winner.Name);
                    });
            }
        });
    }
});
</script>

Upvotes: 0

Views: 177

Answers (1)

xdumaine
xdumaine

Reputation: 10349

Your code is very messy, as you're creating a viewModel object within your applybindings call, and creating viewModel objects directly. Use the constructor syntax, and create new instances of your viewmodels. All you need to do for applyBindings is give it a single instance of your master view model.

Use this JSFiddle as an example, and try to keep your code structured and organized, or it will get extremely messy very quickly.

// this is like a constructor for your members
var memberViewModel = function memberViewModel(data) {
   var self = this;
   self.Id = data.MemberId;
   self.MemberId = ko.observable(data.MemberId);
   self.Name = ko.observable(data.Name);
};

// This is like a constructor for your master view model
var masterViewModel = function() {
   var self = this;
   self.Members = ko.observableArray();

   // put two members into Members
   self.Members.push(new memberViewModel({MemberId: 1, Name: 'Member1'}));
   self.Members.push(new memberViewModel({MemberId: 2, Name: 'Member2'}));

   // set the winner to the first one for default, if you want
   self.Winner = ko.observable(self.Members()[0]);

   //do your ajax in this function
   self.GetNextWinner = function() {
     self.Winner(self.Members()[1]);
   }
};

//Apply bindings gets one instance of your view model
ko.applyBindings(new masterViewModel());

Upvotes: 4

Related Questions