5

I am using Knockout 3.2 and the new component system. I am trying to have components that include sub-components.

Home Page (component - with HomePageViewModel) NewsFeed1 (component with HomePageViewModel.NewsFeedViewModel1) NewsFeed2 (component with HomePageViewModel.NewsFeedViewModel2)

HomePageViewModel

var viewModel = (function () {
    function viewModel() {
        this.message = ko.observable("Welcome to DKT!");
        this.newsFeedViewModel = new gr.viewModel();
        this.newsFeedViewModel2 = new gr.viewModel();
        this.newsFeedViewModel.message("Message 1");
        this.newsFeedViewModel2.message("Message 2");
    }
    return viewModel;
})();

NewsFeedViewModel

var viewModel = (function () {
    function viewModel() {
        this.message = ko.observable("This is the profile!");
    }
    return viewModel;
})();

As you can see the HomePageViewModel contains both the NewsFeedViewModel. I now want to be able to use these as the DataContext/BindingContext of my two components but this does not seem to work.

Home.html

<news-feed data-bind="newsFeedViewModel"></news-feed>
<news-feed data-bind="newsFeedViewModel2"></news-feed>

Both these components do not use the ViewModels from the HomePageViewModel but uses a new NewsFeedViewModel. How can I make the datacontext of both these components bind to the viewModels stored in the top component (home)?

Tanner
  • 22,205
  • 9
  • 65
  • 83
user2465083
  • 595
  • 3
  • 12

1 Answers1

4

Generally, you would want to supply your component with any data via params. For example, with your structure, you could create the component like:

ko.components.register("news-feed", {
    viewModel: function (params) {
       this.vm = params.vm;
    },

    template: "<h2>News Feed</h2><div data-bind=\"text: vm.message\"></div>"
});

Then, you would define the elements like:

<news-feed params="vm: newsFeedViewModel"></news-feed>

<news-feed params="vm: newsFeedViewModel2"></news-feed>

You could choose to pass the message in directly for each and/or choose whatever names make sense for your params (rather than vm).

Sample: http://jsfiddle.net/rniemeyer/fssXE/

RP Niemeyer
  • 114,592
  • 18
  • 291
  • 211
  • Hi again, would you please have a look to the following code http://jsfiddle.net/fssXE/3/. I have added a function in the viewModel, and bound it to a function in the viewModel. At such point, if I try to access any data from the viewModel it will always be undefined. I have not been able to access the data from functions in the viewModel. – user2465083 Jul 12 '14 at 14:54
  • 2
    You've run into a limitation of the `click` binding in Knockout. It always uses the current `$data` object as the `this` value when calling the event handler function. My [Knockout Punches](http://mbest.github.io/knockout.punches/) library modifies `click` (among other things) to work the way you expect: http://jsfiddle.net/fssXE/5/ – Michael Best Jul 13 '14 at 09:25
  • 2
    otherwise, @user2465083, you can use a `with: vm` within your component's template and then bind directly to the methods/properties on `vm` and it will have the right context. Here is a sample: http://jsfiddle.net/rniemeyer/3vE3S/ – RP Niemeyer Jul 13 '14 at 13:15