3
votes

So with the introduction of components and custom elements it seems a lot easier to encapsulate your logic and markup, however I am a bit unsure how to make use of components within foreach sections when you need to pass in a viewmodel.

So my current scenario is that I have a view model which looks something like:

function SomePartialViewModel()
{
    this.Name = ko.observable();
    this.Score = ko.observable();
    this.SomeDate = ko.observable();
}

function SomeViewModel()
{
    this.DataFromWebServiceCall = ko.observableArray();

    this.GetDataFromServer = function(){
        // get some data from service and populate DataFromWebSeriviceCall with instances of SomePartialViewModel
    }
}

Now in the above we have a POJO to contain partial data, and we have a main view model for the view which will contact a web service or something, and populate its array with instances of the partial. Then this would currently be used like so:

<div id="partial-data" data-bind="template: { name: 'partial-view', foreach: DataFromWebServiceCall }"></div>

<div class="partial-view">
    <label data-bind="text: Name"></label>
    <label data-bind="text: Score"></label>
    <label data-bind="text: SomeDate"></label>
</div>

Now assume the .partial-view is in a script tag with correct template name etc and is a correct template, then the #partial-data is in the main view and wants to display all the instances on the page. Now currently it all works, but I would like to move to a more component based model, and currently we can see that the template relies upon the SomePartialViewModel data, so we have our template and our viewmodel for that component, however the problem is around getting the viewmodel into the component, as currently you register the component at setup time, then you use params to populate chunks of it. However in this case I want to pass in the viewmodel to the component at binding time...

So I was wondering how I can go about doing this, as I imagine I could register the component with a template but no viewmodel, but is there the notion of a data style binding where I can set the $data property and move to a foreach from a template binding on the view?

Hopefully the problem I am trying to solve can be seen and any info would be great.

2

2 Answers

1
votes

There are loads of ways to pass values and/or viewmodels to components using the params.

If you use the createViewModel method, you can just pass in the viewmodel via the params and use the partial viewmodel as the component viewmodel:

ko.components.register("partial-view", {
    viewModel: {
        createViewModel: function (params) {
            return params.value;
        }
    },
    template: "<div>Partial View for <b data-bind='text: Name'></b></div>"
});

You can see a working example in this fiddle: http://jsfiddle.net/Quango/fn1ymf9w/

0
votes

You can define viewModels under viewModels :)

just like defining an observable you can define another viewModel and using "with" binding you can create a component based model you desire.

First you create your components and sub-Components and sub-sub-sub-Components etc viewModels seperately.

var SomePartialViewModel = function()
{
    this.Name = ko.observable();
    this.Score = ko.observable();
    this.SomeDate = ko.observable();
}

var SomeViewModel = function()
{
    this.DataFromWebServiceCall = ko.observableArray();

    this.GetDataFromServer = function(){
        // get some data from service and populate DataFromWebSeriviceCall with instances of SomePartialViewModel
    }

    this.SPM = new SomePartialViewModel(); // partial-1
}

And then you create a MainViewModel and bind all the main elements here.

var MainViewModel =  function() {

    var self = this;

    self.SVM = new SomeViewModel();

    self.SPM = new SomePartialViewModel(); // partial-2
}
ko.applyBindings(new MainViewModel());

then in your html you can create your components obeying the context you created on knockout entities

    ...

    <body>
    <div data-bind="with: SVM">
        ....
        <div data-bind="with: SPM">
            <!-- partial-1 data -->
        </div>
        ...
    </div>


    <div data-bind="with: SPM">
        <!-- partial-2 data -->
    </div>
    </body>
...

You may want to create seperate files for your component models and using a modular script loader like Require js you can bind all together to a complete component based knockout web application