Multiple viewmodels sharing data

6 posts, 0 answers
  1. Brandon
    Brandon avatar
    15 posts
    Member since:
    Sep 2012

    Posted 08 Feb 2013 Link to this post

    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...

  2. Alexander Valchev
    Admin
    Alexander Valchev avatar
    2895 posts

    Posted 12 Feb 2013 Link to this post

    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!
  3. Brandon
    Brandon avatar
    15 posts
    Member since:
    Sep 2012

    Posted 12 Feb 2013 Link to this post

    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.
  4. Brandon
    Brandon avatar
    15 posts
    Member since:
    Sep 2012

    Posted 12 Feb 2013 Link to this post

    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.
  5. Alexander Valchev
    Admin
    Alexander Valchev avatar
    2895 posts

    Posted 14 Feb 2013 Link to this post

    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!
  6. cluengas
    cluengas avatar
    2 posts
    Member since:
    Jan 2012

    Posted 09 Sep 2013 Link to this post

    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.
Back to Top