Telerik offers a fantastic library called Kendo UI. They’ve converted all of the objects into Angular Directives. They’re great, except there are some issues that really arise from the actual platform. Angular is very data-centric. You don’t pick an object and then change it, as you do in jQuery, you define the parameters of the object as variables and then let the data do the work naturally.
Kendo Grids, in particular, are objects which are created and then populated with Kendo Datasource objects. With angular we really want the object to be created and then populate automatically as the data is pulled. The Kendo Datasource has a read feature, which has caused endless trouble for us. We’ve been putting callback functions within the transport section of the datasource, so we can hit it with a factory, but it is always causing issues.
Now, we’ve converted to using TypeScript and have finally given up entirely on the Kendo Datasource in favor of Kendo ObservableArrays. With Angular, this gives you the power to manage the data any way you want.
Here’s a quick sample of how this is done.
module Controllers.Admin.Users { class UserListCtrl { static $inject = ['$http', 'adminFact']; public Users: Array; public gridOptions: kendo.ui.GridOptions; public mydata: kendo.data.ObservableArray; constructor( private $http: ng.IHttpService, private adminFact: Application.Services.IAdminService, ) { var self = this; self.Users = []; self.mydata = new kendo.data.ObservableArray(self.Users); self.LoadUsers() this.gridOptions = { dataSource: self.mydata , filterable: { mode: "row" }, scrollable: { virtual: true }, sortable: { mode: "single", allowUnsort: false }, selectable: true, height: $(document).height() - 230, columns: [ { field: "UserId", title: "User#", width: "80px", encoded: false, filterable: { cell: { showOperators: false } } } , { field: "FirstName", title: "First", width: "180px", encoded: false, filterable: { cell: { showOperators: false } } } , { field: "LastName", title: "Last", width: "180px", encoded: false, filterable: { cell: { showOperators: false } } } ] }; } LoadUsers() { var self = this; /* this is a a factory that is simply returning an $http.get */ self.adminFact.Users(function (response: any) { self.$log.debug("Loaded Users"); self.Users = response.data; self.mydata.push.apply(self.mydata, self.Users); }); } } app.controller("UserListCtrl", UserListCtrl); }
The view simply has this: (note: I’m using controllerAs vm)
User List
You simply declare a public variable so it’s accessible in your class (and view if you want)
public mydata: kendo.data.ObservableArray;
now, that array needs to be the datasource in the options that define the array.
First you initialize it so you get the grid, but with an empty array.
var self = this; self.Users = []; self.mydata = new kendo.data.ObservableArray(self.Users);
Now, in this case, I’m using “Users” because I’ve defined an interface for Users, but it really doesn’t need it. That’s just because we’re trying to make everything explicitly typed. You could just have it be
self.mydata = new kendo.data.ObservableArray([]);
Once you’ve got that initilized, you can just build the object structure and let Angular do the rest of the work for that.
this.gridOptions = { dataSource: self.mydata , filterable: { mode: "row" }, etc.etc.etc...
Now the magic. That ObservableArray. Kendo keeps an eye on it, but you need to know how to do it. You need to use “Apply” to get it recognized.
If you look in the return of our factory call, the data comes in, (I’m not going into the factory construction, you can read one of the other articles for that). Once the data comes in, you “push” it into the empty array. Remember, you don’t just set it equal to that value, it has to get pushed AND applied. It isn’t like a normal javascript push, you’re adding them together. like this:
LoadUsers() { var self = this; self.adminFact.Users(function (response: any) { self.Users = response.data; self.mydata.push.apply(self.mydata, self.Users); }); }
The data comes back, we set the Users array equal to the response and then we “push”, but it’s really like a “merge”, because you include the object within the push.apply().
Once you do that, you’re golden. For the rest of the time, you can edit that array, and push/apply the updates and the grid will reflect immediately.
Since I didn’t see anyone using TypeScript, I wrote this post, but here are some more references of people that posted helpful stuff while I was researching how to do this: