Blogs

Batch CRUD Operations With Kendo UI DataSource

by | Comments 10

Last week we posted a primer on the DataSource and Models that are available in the Beta 2 release.  The post showed some basic operations with the models.  Today we follow up with a more in-depth look at the DataSource doing actual CRUD operations and generating views.

Views

In addition to binding Kendo UI widgets to the DataSource, you can also use the Kendo UI Templates with the DataSource to build views.  This gives you absolute control over the rendering of the UI and as we might have mentioned before, Kendo UI templates are super fast.

I recommend reading the article that introduces the DataSource with Models before reading this post as I'm going to skip some of the basics and jump right into it.

One of the things that I’m going to do differently this time is to generate a view off the model using Kendo UI templates.  Up until now we have mostly demonstrated using Kendo UI widgets with the Kendo UI DataSource because they are so quick and easy to setup.  The Kendo UI Templates can also be used to render dynamic views off of the DataSource.

A Quick Templates Primer

Templating is a fairly defined area of JavaScript development and there is no shortage of template engines for you to chose from.  Kendo UI comes bundled with it’s own razor fast templating engine.  Kendo UI Templates allow you to mix HTML and JavaScript expressions in the same block.  A template block could be as simple as the following:

That is just a simple text substitution.  It is also possible to mix JavaScript expressions in with the templates.  JavaScript blocks are denoted by a ‘#’ on either side.  Template substitution values in the HTML are denoted by a ‘#=’ and the front and a closing ‘#’

 

Now you are starting to see the power of using templates.  Combined with the DataSource, they allow you dynamically render pieces of your UI which are often referred to as “Views” in common JavaScript MVC frameworks.

Dynamically rendering views is powered by the kendo.render() method.  The render method takes in two arguments.  The first is a Kendo UI Template, and the second is an array of data to iterate over and create HTML for each item based on the template that was passed in.

We could then refactor the above scenario and pass the array of colors directly into the render method.

Views + DataSource For DataBound Awesomeness

So how do we combine templates with the DataSource?  We’ve seen how to easily bind widgets to the DataSource using their DataSource property, but it’s just as easy to render our views off the DataSource.  The DataSource has a “change” event that we can bind to.  That event is fired whenever the data changes.

But the real impressive power here is when we add Models into the mix.  We can create a DataSource with a model definition that will support a full CRUD implementation.  To take it even one step further, we can separate our logic into single operations or batch operations simply by specifying the “batch” mode for updates on the DataSource.

To render a template with the Kendo UI DataSource, you first define the template, then bind it to the “change” event on the DataSource (which is fired whenever the DataSource performs a CRUD operation) and call the kendo.render() function. 

Using models with the DataSource is as easy as defining the Model and specifying the “id” property.  If your ID is named ID (case insensitive), the model will automatically pick this up and map it as the ID.  Any other properties will be pushed onto the model objects.  The schema of the DataSource then gets set to the Model. 

Item = kendo.data.Model.define({
     id: "ID"
});

template = kendo.template($("#template").html());

pub.dataSource = new kendo.data.DataSource({
     transport: {
          read: {
               url: ("Home/Read")
          }
     },
     schema: {
           model: Item
     },
     change: function () {
          $("#items").html(kendo.render(template, this.view()));
      }
});
 

Take Care Of The CRUD

CRUD operations are defined on the DataSource exactly like the read is in the transport, with the exception of the fact that “delete” is set as “destroy” because “delete” is a keyword in JavaScript.

Side Note: Ever wondered where and when you should exactly use the delete in JavaScript?  Check out this article which will give you insight not only into the delete, but also context and scoping.

The DataSource now looks like this.

Item = kendo.data.Model.define({
     id: "ID"
});

template = kendo.template($("#template").html());

pub.dataSource = new kendo.data.DataSource({
     transport: {
          read: {
               url: ("Home/Read")
          },
          create: {
               url: ("Home/Create"),
               type: "POST"
          },
          destroy {
                url: ("Home/Delete"),
                type: "DELETE"
          }
     },
     schema: {
           model: Item
     },
     change: function () {
          $("#items").html(kendo.render(template, this.view()));
      }
});

 

Notice how I specified the “type” there.  That’s to specify which type of HTTP request to use.  Actually, these methods wrap the jQuery.ajax() method, so anything you specify in the Read, Create, Update or Destroy options on the transport will be passed down to the jQuery.ajax() function.

The Model uses an Observable Pattern so that changes are tracked and concerned parties are notified appropriately.  A model object can be pulled off the DataSource by getting a reference to the DataSource and calling the get() method.  That model object can then be modified by calling the set() method.  Adds and Deletes can be called in a similar way.

// get the model item by id
var model = dataSource.get(0);

// the model might look something like this // { id: 1, Name: "Item 1", Decription: "An Item" } // update the item
model.set("Description", "A More Awesome Item");

// create a new item - do not specify the id. this is how // the data source knows this item needs to be sent to // the server for creation.
dataSource.add({ Name: "Item 2", Description: "Another Item" });

// delete the item
dataSource.remove(model);

This will update the model and the collection of models on the DataSource.  Sending the change to the server is as easy as telling the DataSource to sync.

dataSource.sync();
That will fire all of the appropriate create, update or delete methods on the server depending on what has changed in the model.

 

The Sample Application

No JavaScript model/view example is complete without a Todo List application.You can check out the Kendo Todo List Application here.

A Note To IE 7 & 8 Users: Kendo UI will fully support IE 7 & 8 at official launch (end of this month), but at the time of this writing there is an issue with the Kendo UI DataSource and IE 7 & 8 that will cause this Todo List Application not to work for you. Please check back after official release and I will update the bits.

The Todo List application uses the Kendo UI DataSource and Templates together to render the views to the UI. It also handles updating the server and the UI when the user makes changes to the list.

Updating In Batch

If you set the batch: true property on the DataSource, it will send operations in batches.  For instance, if I delete 3 model items and call sync on the DataSource, it will by default issue 3 delete commands to the server.  Check it out.

image

However the batch:true command sends all of the data together in one shot to the server saving you precious round-trips when you can avoid them.  Here is how it looks in batch mode.

image

A special note on the notation for batch operations.  Depending on what server side platform you are using, you may have to format the parameters a special way.  In my example, I am using ASP.NET MVC which has notorious problems mapping parameters when they are coming in as an array.  Fortunately, you can take complete control over the parameters and how they are formatted by specifying the "parameterMap” option.

destroy: {
     url: "Home/DeleteBatch",
    type: "POST",
},
parameterMap: function (data, type) {
     if (type == "destroy" || type == "create") {
          var items = {};
          $.each(data.models, function (index, item) {
                for (var key in item) {
                    items["[" + index + "]" + "." + key] = item[key];
                }
           });

           return items;
     }
}
 

You can check out the application in both single and batch update mode.

Single Update Mode

Batch Update Mode

Download the Beta 2 bits and begin creating dynamic applications with the Kendo UI DataSource, Models and Templates.

About the Author
is a web developer living in Nashville, TN. He enjoys working with and meeting developers who are building mobile apps with jQuery / HTML5 and loves to hack on social API's. Burke works for Telerik as a Developer Evangelist focusing on Kendo UI. Burke is @burkeholland on Twitter.

10 Comments

  1. 1 Vesselin Obreshkov 09 Nov 2011
    In Chrome if you keep adding stuff sometimes it will not show you your last entry, however, if you then add another entry it will pop up with both, the one you just entered and the one that you entered before that but didn't show up. No errors in the JavaScript console. I was just adding the letters of the alphabet (a,b,c) in the Batch Update Mode demo. I'm running Chrome 16.
  2. 2 Burke 11 Nov 2011
    @Vesselin

    I have been able to reproduce this issue in Chrome.  I'm looking at trying to track down exactly what is happening and I'll post an update soon.  It appears to be an async programming issue with the way I architected my event handling for the application :)
  3. 3 Tom 13 Nov 2011
    can you please show off the source code of Kendo Todo List ?
  4. 4 Burke 18 Nov 2011
    @Tom

    Of course!   Sorry I didn't include that in the post.  Here is a link to the zip file containing an ASP.NET MVC 3 project.

    http://dl.dropbox.com/u/19593893/KendoTodo.zip
  5. 5 Danish 07 Feb 2012
    Great write up. I downloaded the app and tried to run it locally on ie9 but it doesnt seem to work properly for example the button clicks dont work. Interestingly, if I start the developer tools and refresh, it starts working. Any idea what could be wrong? 
  6. 6 Burke 07 Feb 2012
    @Danish

    It's because I'm doing a console.log() and IE 9 chokes on that until you open developer tools.

    Thanks for pointing this out.  I will update the zip.
  7. 7 Yulius 21 Mar 2012
    Hi Burke, nice article. I wonder have you update the source? I would like to see the whole code. The one in dropbox link above is not available anymore. Thanks.
  8. 8 leanne 26 Apr 2012
    I would also like to see the source code if possible but the link to the zip file is not working.
  9. 9 Burke 01 May 2012
    Sorry everyone!  That was a personal DropBox folder and got deleted when I maxed out my space with memes and animated GIF's. 

    I added the project to our GitHub page with the other MVC Examples.
  10. 10 Devon 14 Aug 2012
    Hi Burke.

    I'm having an issue updating my datasource. Each record in my datasource has some details (Name, Address etc), but there is also have an array of "Packages" within each record. 

    When I call model.set() it makes the changes locally but I cannot push those changes through to the remote datasource. I have tried dataSource.sync() and it also doens't work.

    Here's my code so far.

    function saveChanges(e) {
                  var button = e.button,
                  item = packageDataSource.get(button.data("itemId"));
                  packageId = item.ID;
                  // get the model item by id
                  var model = dataSource.get(id);
                  console.log(model.Packages[packageId]);
                  // the model might look something like this // { id: 1, Name: "Item 1", Decription: "An Item" } // update the item
                  model.Packages[packageId].set("Status", newPackageStatus);
                  //console.log(model.Packages[packageId]);
            }

Comment

  1.