This is a migrated thread and some comments may be shown as answers.

Multiple viewmodels sharing data

5 Answers 710 Views
MVVM
This is a migrated thread and some comments may be shown as answers.
Brandon
Top achievements
Rank 1
Brandon asked on 08 Feb 2013, 10:27 PM
I am attempting to create wizard like view in which each page contains it's own viewmodel

I started out doing something like this to get the templates right: 
<div id="example" data-template="template" data-bind="source: locales"></div>
 
<script id="template" type="text/x-kendo-template">
   <div>
       <label data-bind="text: target"></label>
       <select data-text-field="Filename" data-value-field="Path" data-bind="value: Path, source:parent().parent().uploadedFiles" data-role="dropdownlist"></select>
   </div>
</script>
var viewModel = kendo.observable({
    uploadedFiles : [{Filename:"...", Path:""}, {Filename:"1", Path:""}, {Filename:"2", Path:""}],
    locales: [{ target: 'German'}, { target: 'French'}, { target:  'Italian'}, { target:  'Japanese'}, { target: 'Chinese (Simplified)'}]
});
 
kendo.bind($("#example"), viewModel);
Everything works fine: http://jsfiddle.net/RyD54/

However, the subsequent pages need to have knowledge of the previous pages viewmodel's data in order to properly display options.

I have tried directly accessing the second viewmodel like this:
<div id="example" data-template="template" data-bind="source: locales"></div>
 
<script id="template" type="text/x-kendo-template">
   <div>
       <label data-bind="text: value"></label>
       <select data-text-field="Filename" data-value-field="Path" data-bind="value: Path, source:uploadedFiles" data-role="dropdownlist"></select>
   </div>
</script>
var viewModel2 = kendo.observable({
    selectedLocales: ['German', 'French', 'Italian', 'Japanese', 'Chinese (Simplified)']
});
 
var viewModel = kendo.observable({
    uploadedFiles : [{Filename:"...", Path:""}, {Filename:"1", Path:""}, {Filename:"2", Path:""}],
    locales: viewModel2.selectedLocales
});
 
kendo.bind($("#example"), viewModel);
Which ends up producing garbage in the drop down lists. http://jsfiddle.net/LvyB3/

I have tried modifying the locales value to be a dependent observable, thinking that accessing the second viewmodel directly changes the scope:
var viewModel2 = kendo.observable({
    selectedLocales: ['German', 'French', 'Italian', 'Japanese', 'Chinese (Simplified)']
});
 
var viewModel = kendo.observable({
    uploadedFiles : [{Filename:"...", Path:""}, {Filename:"1", Path:""}, {Filename:"2", Path:""}],
    locales: function() {
        return viewModel2.get("selectedLocales");
    }
});
 
kendo.bind($("#example"), viewModel);
But that produces the same garbage data. http://jsfiddle.net/yarut/

I'm not sure what I am doing wrong to access the uploadedFiles list properly.

Any help would be appreciated.

EDIT

The issue has become a bit more complicated: In production the list of source languages is going to be coming from a multi-select in the other viewmodel. My idea is to create a calculated field that builds a observableobject that contains the selectedLanguages, an instance of the uploadedFiles array and a selectedFile variable to hold the selection:

aspx:

<div id="example2">
    <h5>Target</h5>
    <select multiple="multiple" data-value-field="id" data-text-field="name" data-bind="source: availableLocales, value: selectedLocales"></select>
</div>
 
<div id="example">
    <div  data-template="template" data-bind="source: locales"></div>
</div>
 
<script id="template" type="text/x-kendo-template">
   <div>
       <label data-bind="text: target"></label>
       <select data-text-field="Filename" data-value-field="Path" data-bind="value: selectedFile, source:files" data-role="dropdownlist"></select>
   </div>
</script>

javascript:

var viewModel2 = kendo.observable({
    selectedLocales: [],
    availableLocales: [{id:1, name:'German'}, {id:2, name:'French'}, {id:3, name:'Italian'}, {id:4, name:'Japanese'}, {id:5, name:'Chinese (Simplified)'}]
});
 
var viewModel = kendo.observable({
    uploadedFiles : [{Filename:"...", Path:""}, {Filename:"1", Path:""}, {Filename:"2", Path:""}],
    locales: function() {
        var selected = viewModel2.get("selectedLocales");
        var availableFiles = this.get("uploadedFiles");
        var processedLocales = [];
        for (var i = 0; i < selected.length ; i++) {
            processedLocales.push({ target: selected[i].get("name"), files: availableFiles, selectedFile: null });
        }
        return processedLocales;
    }
});
 
kendo.bind($("#example2"), viewModel2);
kendo.bind($("#example"), viewModel);

fiddle: http://jsfiddle.net/fHrVK/

Of course this doesn't work either...

5 Answers, 1 is accepted

Sort by
0
Alexander Valchev
Telerik team
answered on 12 Feb 2013, 03:44 PM
Hello Brandon,

Thank you for getting in touch with us.

Mixing the ViewModel is not supported - it will most likely cause troubles connected with parent detection. I cannot understand what is the problem to use a single View-Model?

I would like to remind you that KendoUI MVVM bindings are not JavaScript. This is not a valid binding expression:
data-bind="value: Path, source:parent().parent().uploadedFiles"

Also please do not bind the template to array of strings. The string value cannot be transformed to observable object which causes a lot of troubles. As an example its parent cannot be found.

What exactly is the problem with the second last example? There are no JavaScript error, what is supposed to happen?

Regards,
Alexander Valchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Brandon
Top achievements
Rank 1
answered on 12 Feb 2013, 04:50 PM
Thanks for the feedback.

I'm getting much closer to my intended goal of dynamically creating new rows using the template based on the selected items from a multi-select in a separate viewmodel. Here's a fiddle of my progress: http://jsfiddle.net/a9gWn/

I don't like the idea of having to do active monitoring and handling of each change, but if it works it works.

To answer your questions, there is no actual problem with using a single viewmodel other than a bunch of re-work. The decision to use multiple viewmodels was made before I started on the project.

I got the parent() call from another thread here on the forums here: http://www.kendoui.com/forums/framework/mvvm/custom-binding-and-complicated-binding-path.aspx

It appears the functionality has been deprecated.
0
Brandon
Top achievements
Rank 1
answered on 12 Feb 2013, 05:10 PM
This one is almost completely there: http://jsfiddle.net/a9gWn/1/

The only problem being that the locales observablearray is cleared everytime the selectedLocales updates. Which is OK, but not ideal.
0
Alexander Valchev
Telerik team
answered on 14 Feb 2013, 03:14 PM
Hi Brandon,

Thank you for the feedback. I am glad to hear that you managed to resolve the problem.

Yes, the parent() call is deprecated, there is no need to use it with the current KendoUI version - Kendo MVVM will automatically search the parents.

Regards,
Alexander Valchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
cluengas
Top achievements
Rank 2
answered on 09 Sep 2013, 06:36 AM
Brandon,
Thanks a lot for this post and figuring out how to solve this issue. I've been banging my head to the wall just to figure out how to use multiple view models.
Now I have to try with nested view models (is it possible at all?).
Cheers.
Tags
MVVM
Asked by
Brandon
Top achievements
Rank 1
Answers by
Alexander Valchev
Telerik team
Brandon
Top achievements
Rank 1
cluengas
Top achievements
Rank 2
Share this question
or