Binding MVVM viewmodel to a schemaModel /datasource

Thread is closed for posting
33 posts, 1 answers
  1. Carl
    Carl avatar
    15 posts
    Member since:
    Nov 2010

    Posted 06 Mar 2012 Link to this post

    Hi,

    Could someone please provide an example of the correct way to bind a viewmodel to either a schemamodel  or datasource?

    Perhaps, I'm blind, but I can't find one.  :)


    Thanks!
  2. Atanas Korchev
    Admin
    Atanas Korchev avatar
    8462 posts

    Posted 06 Mar 2012 Link to this post

    Hello,

     Could you clarify what you mean? A view-model is bound to a view (UI elements).

    Greetings,
    Atanas Korchev
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  3. Kendo UI is VS 2017 Ready
  4. Carl
    Carl avatar
    15 posts
    Member since:
    Nov 2010

    Posted 06 Mar 2012 Link to this post

    Hi,

    Yes, I'd like to bind a viewmodel to a schema model or a datasource somehow, so I can post the values of it like a form.  Am I misunderstanding the usage?

    Thanks again  :)
  5. Atanas Korchev
    Admin
    Atanas Korchev avatar
    8462 posts

    Posted 06 Mar 2012 Link to this post

    Hi,

    I am sorry but I still don't understand. A view-model is a representation of your data (the model) which is bound to a view (the UI elements - a form in your case). What is the data in your case?

    All the best,
    Atanas Korchev
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  6. Carl
    Carl avatar
    15 posts
    Member since:
    Nov 2010

    Posted 06 Mar 2012 Link to this post

    Sorry for the misunderstanding,  I have a jsonp data source, I'd like to be able to populate a form with its fields, incorporating the view model and allowing create and edit records it retrieves and post them back.

    Similar to the scenario in the Similar to the scenario in the "Get Started With The Kendo UI Datasource" video @  http://www.youtube.com/watch?feature=player_embedded&v=FhHMOjN0Bjc#t=313s

    But incorporating a viewmodel as well.
  7. Carl
    Carl avatar
    15 posts
    Member since:
    Nov 2010

    Posted 06 Mar 2012 Link to this post

    My question stems from the MVVM demo: "Kendo MVVM is an implementation of the MVVM pattern which is seamlessly integrated with the rest of the Kendo framework (widgets and DataSource)."

    http://demos.kendoui.com/beta/web/mvvm/source.html 


    How does it integrate?  :)
  8. Kai Schiffer
    Kai Schiffer avatar
    5 posts
    Member since:
    Feb 2010

    Posted 06 Mar 2012 Link to this post

    I like to back up the original question. How is the ViewModel populated via JSon? In all your example the VM values are hardcoded. We know how to fill a dataSource, so: can we do the same for a VM? Or can we point the VM to the populated dataSource?

    And how are the VM fields declared without immediately assigning a concrete value, as in your examples this seems always to be done?

    Greets and thanks!
  9. Carl
    Carl avatar
    15 posts
    Member since:
    Nov 2010

    Posted 06 Mar 2012 Link to this post

    Thank you for providing some more clarity to my question :)
  10. Jaap
    Jaap avatar
    96 posts
    Member since:
    Oct 2012

    Posted 06 Mar 2012 Link to this post

    Yes, please provide us an example. This is exact the question I am researching now.
    I have a datasource populated with one entity.
    How should I expose that with my viewmodel so that the elements can bind to it.
    Need an example which edits an entity from a datasource.
    Looks to me this is the primary usecase, but none of your examples shows this.

    And please, give also an example on how to populate a dropdownlist with serverdata through databinding.

    Regards, Jaap
  11. Dustin
    Dustin avatar
    79 posts
    Member since:
    Oct 2012

    Posted 06 Mar 2012 Link to this post

    I too am trying to make a remote data call in my VM to set a datasource, but am getting an error doing so. I probably am not doing it right, but here is the code I am using below since your example only hard codes data sources in the VM and not make web service calls which is how it is almost always done in real world applications.

    I also attached a screen shot of the error I get.

    var viewModel = kendo.observable({
                     
                    serviceTypeSource: new kendo.data.DataSource({
                        transport: {
                            read: {
                                type: "POST",
                                url: "../Services/ServiceCommonService_Js.svc/GetServiceTypes"
                            }
                        },
                        schema: {
                            data: "d"
                        }
                    }),
     
                    serviceTypeValue: null,
     
                    serviceTypeDisplayValue: function () {
                        return kendo.stringify(this.get("serviceTypeValue"));
                    }
     
                });
  12. Carl
    Carl avatar
    15 posts
    Member since:
    Nov 2010

    Posted 07 Mar 2012 Link to this post

    EDIT: Noticed that I had "editable: false" on all of my Schema objects still, removing this causes a two-way bind, otherwise updates back to the datasource are ignored, but the viewModel itself is still updated.

    EDIT 2: This example is hardcoded to grab record 0 from the DS, see the change log link for grabbing specific records.

    -----------------

    Wrote this quick and nasty, but it seems to be functional.

    http://www.kendoui.com/documentation/changes-and-backward-compatibility.aspx  

    I found this in the change log:

    DataSource data contains ObservableObjectinstead of raw data records 


    var contractsSchemaModel = kendo.data.Model.define({
        id: "Id",
        fields: {
            Id: { editable: false, type: "number" },
            Name: { editable: false, type: "string" },
            SupplyAddress: { editable: false, type: "string" },
            BillingAddress: { editable: false, type: "string" }
        }
    });
     
    var sharableDataSource = new kendo.data.DataSource({
        transport: {
            read: {
                type: "get",
                url: "<PLEASE ENTER YOUR URL HERE>",
                dataType: "jsonp",
                contentType: "application/javascript; charset=utf-8"
            }
        },
        schema: {
            data: "d",
            model: contractsSchemaModel
        },
        change: function() { // subscribe to the CHANGE event of the data source
            createViewModel(this.view());
        }
    });
     
     
    function createViewModel (schemaView) {
        if(typeof schemaView != "undefined") {
            viewModel = schemaView[0];
             
            kendo.bind($("#mvvmView"), viewModel);
        }
    }
     
    var viewModel;
  13. Answer
    Rosen
    Admin
    Rosen avatar
    3234 posts

    Posted 07 Mar 2012 Link to this post

    Hi all,

    Indeed, the DataSource items are ObservableObject and can be use as MVVM binding source. Here is a basic sample of such usage:

    Regards,
    Rosen
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  14. Jaap
    Jaap avatar
    96 posts
    Member since:
    Oct 2012

    Posted 07 Mar 2012 Link to this post

    Ok, now we use the DataSource item as the viewmodel (example of Rosen and Carl). But that is to easy.
    Let me sketch my an example of my use case:

    DataSource with model { field1 (int), field2 (string), field3 (int with dropdownlist) }

    HTML Template:
    <div>
        <input type="text" data-bind="value: field1" />
        <input type="text" data-bind="value: field2" />
        <input type="text" data-role="dropdownlist" data-bind="source: field3source, value: field3" />
        <a data-bind="click: save">Save</a>
        <a data-bind="click: cancel">Cancel</a>
    </div>

    Viewmodel: {
        dataSourceItem: DataSource.view()[0],
        field3source: field3sourceDataSource.view(),
        save : function() { .... }
        cancel : function() { .... }
        /* any other function to support the view (visibility, enabling, etc) */
    }

    data-bind="value: field1" will not work because field1 is not a field of the viewmodel.
    Should I use: data-bind="value: dataSourceItem.field1"?
    And about field3source: should that point to a datasource.view()? Or should that be done an otherway?

    Hopefully it is clear what I want to achieve and can you provide me an example.
    The MVVM framework looks promising, but missing the real world examples until now.
    Regards, Jaap
  15. Carl
    Carl avatar
    15 posts
    Member since:
    Nov 2010

    Posted 07 Mar 2012 Link to this post

    Thanks for posting that example.  Quick question: If I select a drop-down, make a change, choose another item from the drop-down and make a change, wont that have marked both items dirty in the datasource?  So when you call sync it updates both items?

    How can we rollback a transaction on change, if this is the case?

    Thanks!
  16. Rosen
    Admin
    Rosen avatar
    3234 posts

    Posted 07 Mar 2012 Link to this post

    Carl,
    if you want to revert changes made to a model from the DataSource, you may use DataSource cancelChanges method passing the Model instance which to be reverted.
     
    Jaap,
    You should use "dataSourceItem.field1" in this case. However, with the Q1 2012 Beta version, this case changes will not mark DataSource item as dirty in the DataSource, thus it will not be synced. We are working on adding support for this case and we will try to include it for the official version.

    Regards,
    Rosen
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  17. Dustin
    Dustin avatar
    79 posts
    Member since:
    Oct 2012

    Posted 07 Mar 2012 Link to this post

    My question still is how do you setup a data source in the viewmodel that makes a web service call and then bind your html select to that datasource?
  18. Rosen
    Admin
    Rosen avatar
    3234 posts

    Posted 08 Mar 2012 Link to this post

    Hi Dustin,

    You should not set DataSource instance as field in the ViewModel, but use an already existing collection/model. It can be a collection/model fetch through a DataSource (as shown in the previous examples from this thread) or static data or fetched through $.ajax etc.

    Greetings,
    Rosen
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  19. Jaap
    Jaap avatar
    96 posts
    Member since:
    Oct 2012

    Posted 08 Mar 2012 Link to this post

    @Rosen: that would be nice.
     To set the expectations right:
     
    Suppose I have a dataSource with model { intField, stringField }
     Then I would expect that this viewModel to be able:
     

    var viewModel = {
       /* so I can 2-way bind to modelItem.intField and modelItem.stringField */
       /* This way you can bind the model directly to the view */
       modelItem: dataSource.view()[0],
      
       /* Below the typical viewModel stuff */
      
       /* transform 2-way bind of model field */
       intFieldTransformed: function (value) {
          if (value != undefined) {
             this.get("modelItem").intField = value + 2;
          }
          else {
              return this.get("modelItem").intField - 2;
          }
       }
      
       /* viewModel stuff */
       buttonXxxEnabled: function () {
          return this.get("modelItem").intField != 0;
       }
      
       save: function () {
          .....
       }
    }

     

    And when the modelItem is changed:

    this.set("modelItem") = dataSource.view()[1];

    Then I expect that the bindings to intFieldTransformed and buttonXxxEnabled also are updated in the view

    Regards, Jaap

  20. Carl
    Carl avatar
    15 posts
    Member since:
    Nov 2010

    Posted 08 Mar 2012 Link to this post

    The example Rosen gave already shows this, Jaap, as far as I understand your post.  Maybe try reading his source again, or even mine as well (which is rougher) if you're still seeking answer?

    Hope you find answers :)
  21. Jaap
    Jaap avatar
    96 posts
    Member since:
    Oct 2012

    Posted 08 Mar 2012 Link to this post

    No, the example from Rosen binds the view directly to the model from the datasource.
    In my example I want to have a real viewModel with a reference to the underlying model.

    Jaap
  22. Dustin
    Dustin avatar
    79 posts
    Member since:
    Oct 2012

    Posted 08 Mar 2012 Link to this post

    I am trying to set an item in my view model equal to my datasource's view, but my dropdownlist never updates with the new view. Below is my code. The results are being returned to my datasource, but the dropdownlist doesn't ever load with the results. Am I doing something wrong?

    $(document).ready(function() {
     
                var serviceTypeDataSource = new kendo.data.DataSource({
                    transport: {
                        read: {
                            type: "POST",
                            url: "../Services/ServiceCommonService_Js.svc/GetServiceTypes"
                        }
                    },
                    schema: {
                        data: "d"
                    }
                });
     
                serviceTypeDataSource.read();
     
                var viewModel = kendo.observable({
     
                    serviceTypeView: serviceTypeDataSource.view(),
     
                    serviceTypeValue: null,
     
                    serviceTypeDisplayValue: function () {
                        return kendo.stringify(this.get("serviceTypeValue"));
                    }
     
                });
     
                kendo.bind($("#serviceSearchContent"), viewModel);
     
    });
     
    <div id="serviceSearchContent" style="width:100%;height:500px;">
       <select id="serviceTypes" style="width:300px;"
                    data-role="dropdownlist" data-value-field="ServiceId" data-text-field="ServiceName"
                    data-bind="source: serviceTypeView, value: serviceTypeValue" />
    </div>

  23. Rosen
    Admin
    Rosen avatar
    3234 posts

    Posted 09 Mar 2012 Link to this post

    Dustin,

    Looking at the code you have pasted, I guess that it is not populated due to the fact that DataSource is asynchronous. Thus it is not populated when the ViewModel is created. When using remote data you should use DataSource's change event  to ensure that data is loaded before accessing it.

    Jaap,

    Indeed, the idea is the same as you have described. However, note that the syntax you are using in the pasted code, is not totally correct. 
     
    Regards,
    Rosen
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  24. Jaap
    Jaap avatar
    96 posts
    Member since:
    Oct 2012

    Posted 09 Mar 2012 Link to this post

    @Rosen,

    Yes, I am aware of that. It was more or less meant as pseudo code.

    Thanks, Jaap
  25. Dustin
    Dustin avatar
    79 posts
    Member since:
    Oct 2012

    Posted 09 Mar 2012 Link to this post

    Rosen,

    If you look at my code I do setup the asynchronus datasource in the VM to the datasource's view, but outside of it I call serviceTypeDataSource.read(). So, why when the async call completes and returns data does the VM not automatically update the serviceTypeView item in my VM with the fetched data and then automatically update the input element I setup up bindings on to the VM.

    Can you please be more descriptive with your answer or provide a code example on how to use the MVVM framework with web service calls and have the VM update your binded input elements with the returned data. This is all I need to know and we wouldn't have to keep going back and forth if this information could be provided. This is the 2nd or 3rd time in this thread I have asked this question and I am still not getting a direct answer. Please help, none of your MVVM examples or documentation combine MVVM with web service calls.

    To make my question even simpler....how can I use the MVVM with web service call and bind to my input element?
  26. Adrian
    Adrian avatar
    13 posts
    Member since:
    Feb 2012

    Posted 09 Mar 2012 Link to this post

    I think I am looking for the same thing as well:
    How do you load a record via a defined kendo.data.DataSource into a form that is bound by a ViewModel?

    For example:
    1. I have a grid with a jsonp DataSource.
    2. I want to populate a form on select of a grid row/cell.
    3. The form has more fields than the list of grid columns, and these fields are described in the DataSource schema.
    4. The form to be bound to a ViewModel.
    I hope this is clear.

    Thanks!
  27. Alessandro
    Alessandro avatar
    3 posts
    Member since:
    Feb 2012

    Posted 10 Mar 2012 Link to this post

    Hi,

    I've the same issue described by Adrian and Justin.

    I'd appreciate some help on answering the Adrian questions above.
    thanks.
  28. Rosen
    Admin
    Rosen avatar
    3234 posts

    Posted 12 Mar 2012 Link to this post

    Dustin,

    The approach you have described will not work as serviceTypeView is different array instance that the one from the DataSource. You can find a modified sample, which demonstrates a possible implementation of your scenario here.


    Adrian,
    You should use the sample approach demonstrated in the example from my previous message, but change the DropDownList with a Grid widget.

     
    Regards,
    Rosen
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  29. Adrian
    Adrian avatar
    13 posts
    Member since:
    Feb 2012

    Posted 12 Mar 2012 Link to this post

    I see what is going on now with the example.  The part I was looking for and didn't realize was being done was this on the "Edit Product" dropdown list:
    change: function() {
      var model = dataSource.get(this.value());
      kendo.bind($("#container"), model);
    }


    To expand on this, let's assume the first cell of a grid row (with grid property selectable = "row") has the ProductID to lookup.  You could call this onChange function via your grid "change" event:
    function onChange(arg) {
      var selected = $.map(this.select(), function(item) {
        var prodID = $(item).find(">td:first").text();
        var model = products.DataSource.get(prodID);
        console.log(prodID);
        kendo.bind($("form"), model);
        return prodID;
      });
     
      console.log("Selected: " + selected.length + " item(s), [" + selected.join(", ") + "]");
    }
  30. Adrian
    Adrian avatar
    13 posts
    Member since:
    Feb 2012

    Posted 13 Mar 2012 Link to this post

    I was able to get the row click (change) event of a grid to load a record into a form by binding the form to the DataSource.  My next problem is that the form has a couple HTML select items that were working with the ViewModel binding (specified by an additional array item) but are lost when binding to the DataSource because the schema does not contain those virtual fields.  Stepping through the code, it seems the "source" is lost on those HTML select items.  Is there a way to retain the values in them when binding to the DataSource as well as pre-select the current record value in them?

    The error message when hitting the first HTML select item on binding to DataSource is:
    Uncaught TypeError: undefined has no properties 
  31. Adrian
    Adrian avatar
    13 posts
    Member since:
    Feb 2012

    Posted 13 Mar 2012 Link to this post

    I Just resolved the previous issue.  I was missing this attribute on the HTML Select:
    data-role="dropdownlist"
Back to Top
Kendo UI is VS 2017 Ready