One thing I have missed a lot with Kendo, that I was accustomed to with KnockoutJS was the KnockoutJS Mapping Plugin. This was an extremely useful feature to me. I have very much wanted its functionality in kendo, so I took some time and just wrote a small few lines of code to do some of what I used to with knockout.
I don't know if this will ever see the light of day, but I would love to see this kind of thing in the future of kendo.
First, you just declare a mapping. To make this easier, I simply added it to the declaration of a model in kendo.data.Model.define. This particular mapping simply uses a function to merge all children under an array called Tags when it is created, so that they each have a function.
Next, you need an actual function to perform the mapping. I did this with this code.
This will go through the mapping data given, and some JSON data given, and do the appropriate work to call upon the mapping keys and
children functions.
Now, I have a function for merging raw JSON data with a kendo view model.
So then, I can just call this in my view model and javascript like this.
So then, the controller returns data that looks like this.
And the mapping just needs one call, to merge it with the view model, and to map the function onto the tags array. Where data is the data returned from the dataSource.
I think you will find this is extremely useful for building complex models that meet more realistic business needs.
I don't know if this will ever see the light of day, but I would love to see this kind of thing in the future of kendo.
First, you just declare a mapping. To make this easier, I simply added it to the declaration of a model in kendo.data.Model.define. This particular mapping simply uses a function to merge all children under an array called Tags when it is created, so that they each have a function.
var Model = kendo.data.Model.define({
id: "Id",
fields: {
Id: {
type: "string",
},
Name: {
type: "string",
},
Tags: []
},
mapping: {
Tags: {
children: function (data) {
return $.extend(data, {
onRemove: function (e) {
console.log(e);
}
});
}
}
}
});
kendo.mapping = function (source, mapping) {
var name,
value;
// if the user provides us a mapping, we can use that to help
// build the objects appropriately
for (name in source) {
if (source.hasOwnProperty(name)) {
// get the value for this property or item
value = source[name];
// try to determine if this is an array, or just a
// normal object. That will greatly dictate our choice of behavior
if (value instanceof Array) {
// if this is an array, then we will try to check for a
// key in the mapping schema
if (mapping[name].children) {
// if we discover a mapping key for this array, we
// will use it to reconstruct the array data
for (var i = 0; i < value.length; i++) {
source[name][i] = mapping[name].children(value[i]);
}
}
} else {
// attempt to match any non array type keys
if (mapping[name]) {
source[name] = mapping[name](value);
}
}
}
}
return source;
}
children functions.
Now, I have a function for merging raw JSON data with a kendo view model.
kendo.data.ObservableObject.prototype.fromJSON = function (source, mapping) {
var name,
value,
observable = this;
// if there is mapping given, then pass it through that first
if (mapping) {
source = kendo.mapping(source, mapping);
}
for (name in source) {
if (observable.hasOwnProperty(name)) {
observable.set(name, source[name]);
}
}
}
var viewModel = new Model({
Id: null,
Name: null,
Tags: []
});
var dataSource = new kendo.data.dataSource({
transport: {
read: {
url: '/data/items/',
dataType: "json",
type: 'GET'
}
},
schema: {
total: "total",
data: "data"
}
});
Id: "items/1",
Name: "Some Game Item",
Tags: [
{
Id: "tags/1",
Name: "Sword"
},
{
Id: "tags/2",
Name: "Weapon"
}
]
viewModel.fromJSON(data.toJSON(), viewModel.mapping);