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

Binding MVVM viewmodel to a schemaModel /datasource

32 Answers 1807 Views
MVVM
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Carl
Top achievements
Rank 1
Carl asked on 06 Mar 2012, 10:58 AM
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!

32 Answers, 1 is accepted

Sort by
0
Atanas Korchev
Telerik team
answered on 06 Mar 2012, 01:38 PM
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!
0
Carl
Top achievements
Rank 1
answered on 06 Mar 2012, 01:40 PM
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  :)
0
Atanas Korchev
Telerik team
answered on 06 Mar 2012, 01:49 PM
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!
0
Carl
Top achievements
Rank 1
answered on 06 Mar 2012, 01:54 PM
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.
0
Carl
Top achievements
Rank 1
answered on 06 Mar 2012, 01:57 PM
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?  :)
0
Kai Schiffer
Top achievements
Rank 1
answered on 06 Mar 2012, 03:51 PM
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!
0
Carl
Top achievements
Rank 1
answered on 06 Mar 2012, 03:53 PM
Thank you for providing some more clarity to my question :)
0
Jaap
Top achievements
Rank 2
answered on 06 Mar 2012, 04:17 PM
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
0
Dustin
Top achievements
Rank 1
answered on 06 Mar 2012, 11:34 PM

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"));
                }
 
            });
0
Carl
Top achievements
Rank 1
answered on 07 Mar 2012, 06:23 AM
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;
0
Accepted
Rosen
Telerik team
answered on 07 Mar 2012, 08:41 AM
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!
0
Jaap
Top achievements
Rank 2
answered on 07 Mar 2012, 09:25 AM
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
0
Carl
Top achievements
Rank 1
answered on 07 Mar 2012, 09:34 AM
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!
0
Rosen
Telerik team
answered on 07 Mar 2012, 12:45 PM

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!
0
Dustin
Top achievements
Rank 1
answered on 07 Mar 2012, 03:23 PM
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?
0
Rosen
Telerik team
answered on 08 Mar 2012, 08:32 AM
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!
0
Jaap
Top achievements
Rank 2
answered on 08 Mar 2012, 08:50 AM

@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

0
Carl
Top achievements
Rank 1
answered on 08 Mar 2012, 08:58 AM
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 :)
0
Jaap
Top achievements
Rank 2
answered on 08 Mar 2012, 09:25 AM
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
0
Dustin
Top achievements
Rank 1
answered on 08 Mar 2012, 02:54 PM

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>

0
Rosen
Telerik team
answered on 09 Mar 2012, 08:34 AM
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!
0
Jaap
Top achievements
Rank 2
answered on 09 Mar 2012, 08:39 AM
@Rosen,

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

Thanks, Jaap
0
Dustin
Top achievements
Rank 1
answered on 09 Mar 2012, 02:28 PM
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?
0
Adrian
Top achievements
Rank 1
answered on 09 Mar 2012, 10:59 PM
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!
0
Alessandro
Top achievements
Rank 1
answered on 10 Mar 2012, 09:11 PM
Hi,

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

I'd appreciate some help on answering the Adrian questions above.
thanks.
0
Rosen
Telerik team
answered on 12 Mar 2012, 08:31 AM
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!
0
Adrian
Top achievements
Rank 1
answered on 12 Mar 2012, 07:50 PM
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(", ") + "]");
}
0
Adrian
Top achievements
Rank 1
answered on 13 Mar 2012, 03:08 PM
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 
0
Adrian
Top achievements
Rank 1
answered on 13 Mar 2012, 06:56 PM
I Just resolved the previous issue.  I was missing this attribute on the HTML Select:
data-role="dropdownlist"
0
Jeff
Top achievements
Rank 1
answered on 13 Mar 2012, 07:28 PM
Running into an issue (mis?)using the techniques on this page.  Demonstrated here: http://jsfiddle.net/ezX3P/1/

If you click the "Update Window" and "Back" buttons multiple times, it fires a single "alert" like it should, but as soon as you click the "Update Id" on the second screen, it starts duplicating the event bindings (as far as I can tell) so that if you then click on "Back" or "Update Window", they fire twice.  It appears to double every time the "Update Id" button is clicked.
0
Carl
Top achievements
Rank 1
answered on 14 Mar 2012, 02:09 AM
I have seen it double-fire events using the popup editor in the Grid.  I believe I read somewhere when I was half-asleep that this issue will be fixed in release, I think.
0
Jeff
Top achievements
Rank 1
answered on 22 Mar 2012, 06:52 PM
Confirmed that the double-fire issue is fixed in the release version.  Yay!
Tags
MVVM
Asked by
Carl
Top achievements
Rank 1
Answers by
Atanas Korchev
Telerik team
Carl
Top achievements
Rank 1
Kai Schiffer
Top achievements
Rank 1
Jaap
Top achievements
Rank 2
Dustin
Top achievements
Rank 1
Rosen
Telerik team
Adrian
Top achievements
Rank 1
Alessandro
Top achievements
Rank 1
Jeff
Top achievements
Rank 1
Share this question
or