Hello Telerik team,
thank you for your work and support so far.
We have a blocking problem when binding our data to a grid.
The problem is that while the data is initially correctly bound when calling kendo.bind ; the wrong model field is then used when adding new data to the grid data source. This occurs because the grid data source properties name are the same of the model root property names.
I have reproduced the problem in the following dojo : http://dojo.telerik.com/OnuZA
You can see in the previous example that the data is correctly bound initially.
When you enter a new record in the grid it affects the root of the view model and not the array where the data source is bound !
Is it the desired behavior ? If not have you a way to fix this problem until it get fixed in a next release ?
Thank you !
5 Answers, 1 is accepted
The described behaviour is expected because when a DataSource is not used and a new item is added, there is only an empty field in the object. Then the MVVM implementation is bubbling up and checking the parent elements to find the fields, and in this scenario is finding the firstName and the lastName from the ViewModel and it is replacing the initial fields with them.
In this scenario, I can suggest using a DataSource and its schema.model property to set the fields of the DataSource. This will prevent the undesired effect because it will correctly match the fields from the DataSource model:
http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-schema.model
I modified the provided example to work as expected:
http://dojo.telerik.com/uxEPe
I hope this will help to achieve the desired result.
Regards,
Stefan
Telerik by Progress
Hello Stefan,
Thanks for your answer. I tried to implement your proposed example but in our scenario it does not fit well.
When we bind our model with kendo.bind() our model is the json sent by the web server. And our various grids data are expressed as json arrays, and the wrapped in ObservableArrays that we track for a changes detection mechanism.
So our grids data-bind attributes only references "source:MySource" where MySource is an ObservableArrays.
I have not found an easy way to circumvent the problem by assigning a dataSource schema model to the dataSource of the grid at some moment.
I tried to do it in one of our custom binder that do a grid.setOptions({columns: columnsDefinition}) to handle correct column definition. But the data source binding seems to occur after.
I cannot modify our json model to transform my array in a dataSource because it break our changes detection mechanism based on ObservableArray.
Is there an easy way to do this ? I'm thinking of a custom binder instead of "source" but this is becoming a mess.
I think the grid should expose an option to be able to define it's own correct dataSource model when mvvm binding to prevent modifying data outside of the grid's data boundary.
I find this grid default behavior quite strange for the grid when you bind data to it because you are not sure your modification will affect grids data only depending on other model properties renaming. This could become easily a mess after some refactoring.
So I will try a custom "source" binding unless you have an easier solution.
The provided suggestion is the only one which is supported out of the box when the fields of the Grid and the properties of the model have the same names.
Other options are to have specific naming conventions for the properties and the fields to ensure that the names cannot be the same or to use the suggested custom binding.
Apologies for the inconvenience this may cause you.
Please let me know if you need additional information on this matter.
Regards,
Stefan
Telerik by Progress
Here is the typescript implementation in the case that may help someone :
/**
* This allow setting a source with a model to a grid as it is not supported by kendo
*/
let binder = kendo.data.Binder.extend({
init: function(element, bindings, options) {
kendo.data.Binder.fn.init.call(this, element, bindings, options);
const data = bindings.gridSource.get();
const dataSourceSchema = (element.dataSource.schema || {}) as kendo.data.DataSourceSchema;
const dataSourceModel = dataSourceSchema.model || (dataSourceSchema.model = {});
if (dataSourceModel.fields == undefined) {
dataSourceModel.fields = {};
}
const gridColumns = bindings.gridColumns.get();
const gridColumnsLength = gridColumns.length;
for (let index = 0; index <
gridColumnsLength
; ++index) {
const
gridColumn
=
gridColumns
[index];
const
field
=
gridColumn
.field;
if (field == undefined) {
continue;
}
dataSourceModel.fields[field] = gridColumn.defaultValue == undefined
? field
: {
defaultValue: gridColumn.defaultValue
};
}
const
dataSource
=
new
kendo.data.DataSource({
data: data,
schema: dataSourceSchema
});
element.setDataSource(dataSource);
},
refresh: () => {}
});
kendo.data["binders"].gridSource = binder;
kendo.data["binders"].widget.gridSource = binder;
Thank you for sharing the implementation with the Kendo UI community.
We do appreciate the sharing of custom implementations which can be helpful for others.
Regards,
Stefan
Telerik by Progress