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
Could you clarify what you mean? A view-model is bound to a view (UI elements).
Greetings,Atanas Korchev
the Telerik team
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 :)
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
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.
http://demos.kendoui.com/beta/web/mvvm/source.html
How does it integrate? :)
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!
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
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"));
}
});
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 ObservableObjects instead 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;
Indeed, the DataSource items are ObservableObject and can be use as MVVM binding source. Here is a basic sample of such usage:
Rosen
the Telerik team
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
How can we rollback a transaction on change, if this is the case?
Thanks!
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.
Rosen
the Telerik team
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
@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
Hope you find answers :)
In my example I want to have a real viewModel with a reference to the underlying model.
Jaap
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
>
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
Yes, I am aware of that. It was more or less meant as pseudo code.
Thanks, Jaap
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?
How do you load a record via a defined kendo.data.DataSource into a form that is bound by a ViewModel?
For example:
- I have a grid with a jsonp DataSource.
- I want to populate a form on select of a grid row/cell.
- The form has more fields than the list of grid columns, and these fields are described in the DataSource schema.
- The form to be bound to a ViewModel.
Thanks!
I've the same issue described by Adrian and Justin.
I'd appreciate some help on answering the Adrian questions above.
thanks.
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
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(
", "
) +
"]"
);
}
The error message when hitting the first HTML select item on binding to DataSource is:
Uncaught TypeError: undefined has no properties
data-role="dropdownlist"
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.