• .NET Developer Tools DevTools

    UI controls for ASP.NET AJAX, MVC, WPF,
    Silverlight, Windows 8 and Windows Phone

  • Hybrid Mobile Development Icenium

    Cross-platform Mobile Development Tool
    with cloud-based architecture

  • HTML5 / JavaScript Development Kendo UI

    Everything you need to build sites and
    mobile apps with JavaScript and HTML5

  • Testing Tools TestStudio

    One easy tool for Functional, Performance,
    Load and Mobile software testing

  • Web Presence Platform Sitefinity CMS

    Everything for your online business - content
    management, ecommerce, emarketing

  • Agile Project Management TeamPulse

    Simple and intuitive project management
    and collaboration software

Contact us

We are here for you.
  • usa+1‒888‒365‒2779
  • uk+44‒20‒7291‒0580
  • bg+359‒2‒8099850
  • de+49‒89‒2441642‒70
  • au+61‒2‒8090‒1465
  • emailsales@telerik.com
Your account Access to your products, updates and support
Telerik Product Families
  • Your Account
    Your Account
    Log in
  • ABOUT US

    About Telerik

    • Company
    • Press Center
    • Customers
    • Community
    • Careers
    • Contacts
Kendo UI - The way of HTML5
Products ▼
Kendo UI Web Kendo UI Mobile Kendo UI DataViz Server Side Wrappers
Demos Purchase Download
Blogs Documentation
Support ▼
Premium Forums StackOverflow Forums
Resources ▼

Featured Resource

Kendo UI Dojo


Blogs Code Library Demos Documentation FAQ Testing
Premium Forums Roadmap User Voice Videos Webinars More Resources
Contact Us Search
 

Blogs

Breeze.js And The Kendo UI DataSource

Thursday, February 21, 2013 by Kendo UI Team Blog | Comments 11

Hot on the heels of my post on creating a Kendo UI DataSource for a Backbone.Collection, Brandon Satrom and I built a quick hack to see what it would take to integrate Breeze.js with our DataSource.

DataSource All The Things

If you're not familiar with Breeze.js, it describes itself by saying "Rich data for JavaScript apps is a Breeze". Basically, it's a framework to abstract away all of the complexities of calling data APIs through JavaScript. It takes the complexity of understanding not only XHR objects away, like jQuery's ajax method, but also understanding data formats, query parameter formats, integration with specific back-end data sources, and much more.

The basic transport code

Like the Backbone.Collection integration, I'm going to build a custom data transport for Breeze.js. Instead of focusing on the basic CRUD features, though, I want to show some of the more advanced features of reading data: sorting and paging.

To get started, I need a DataSource wrapper that allows me to pass in the needed Breeze.js objects. The end result will be a custom transport that calls through to the Breeze objects through four basic methods: create, read, update, and delete. If you need further review or information on this, be sure to read my previous post on building a DataSource for a Backbone.Collection, and check out the documentation for DataSource transport.

BreezeDataSource

(function ($, kendo, breeze) {
  'use strict';

  // namespace for the extensions
  kendo.data.extensions = kendo.data.extensions || {};

  // constructor function for the custom transport
  function BreezeTransport(entityManager, endpoint){
    this.entityManager = entityManager;
    this.endPoint = endPoint;
  }

  // instance methods for the custom transport
  $.extend(BreezeTransport.prototype, {
    read: function (options) {
      // ...
    },
    create: function (options) {
      // ...
    },
    update: function (options) {
      // ...
    },
    destroy: function (options) {
      // ...
    }
  });

  // Create the custom DataSource by extending a kendo.data.DataSource
  // and specify an init method that wires up needed functionality.
  kendo.data.extensions.BreezeDataSource = kendo.data.DataSource.extend({
    init: function (options) {
      // build the transport and final options objects
      var breezeTransport = new BreezeTransport(options.entityManager, options.endpoint);
      options = $.extend({}, { transport: breezeTransport }, options)

      // Call the "base" DataSource init function and provide our custom transport object
      kendo.data.DataSource.fn.init.call(this, options);
    }
  });
})($, kendo, breeze);

The Breeze EntityManager is the core of what we work with, and is where an app will configure it's back-end specifics. Passing this in to our custom DataSource will allow all of Breeze's flexibility, but still give us the ability to query the data based on the parameters that the Kendo UI DataSource provides to the read method.

Reading data with EntityQuery

Once we have the custom DataSource and transport outlined, we can focus on read data through the EntityQuery object.

This object allows us to form the query that will be sent back to the API, and includes methods three methods that we'll use for sorting and paging:

  • orderBy
  • skip
  • take

These are common method and attribute names used for sorting and paging. The orderBy method is fairly self-explanatory in name. It allows us to sort the results by the configuration we specify. The skip and take methods, in combination, allow us to facilitate paging. These two methods might not be as obvious, though.

Skip, and take a page

When building a paged data source of any kind, paging can be facilitated with two simple parameters: skip and take. Any system that needs to use paging, then, can provide these parameters and end up with the data set that they expect. When a DataGrid or other page-enabled control says it wants page 2 of a data set, and each page is 10 records long, this gets translated in to the skip and take settings.

Given a page length of 10 and a request for page 2, we can do simple math to get the starting point of the data we want to show from the overall result set. Since we want page 2 of data and the page length is 10, we know that we need to skip the first 10 records... the first page of data. This can be calculated with a little bit of code, quite easily:

Calculating skip

var requestedPageLength = 10;
var requestedPageNumber = 2;

var skip = requestedPageLength * (requestedPageNumber-1); // => 10

We're subtracting 1 from the page number so that we can get the starting point of the second page of data, not the end point.

Even when we request page #1, then we don't want to skip anything - we want to start at the beginning of the record set. The formula still works for this scenario: 10 * (1-1) = 0, which says "skip zero records" or "start at the very beginning."

The take parameter of the skip/take combination is the actual number of records that we want to get - the reuested page length. This parameter tells the data source how many records to return, after it has skipped the number that we said to skip.

Take is the page size

var take = requestedPageLength;

The end result of the skip / take combination is a paging system that can be used by nearly any data source and page-enabled control or other code.

Reading paged and sorted data is a Breeze

Integration between Breeze and the transport read method is easy from here. The options parameter that is passed through the method contains three attributes: sort, skip, and take. We can apply these to the Breeze EntityQuery to get the paged and sorted data that has been requested.

Paged and sorted data with Breeze

read: function(options){
  var orderVal = "",
      sortOps = options.data.sort;

  // build sorting the way breeze understands it
  if (sortOps) {
    orderVal = sortOps.field + " " + sortOps.dir;
  }

  // build a query to get the sorted and paged results
  var query = new breeze.EntityQuery(endpoint)
      .orderBy(options.data.sort)
      .skip(options.data.skip)
      .take(options.data.take);

  // ...
}

Note that we're not just grabbing the raw sort value from the options.data.sort. Instead, we are taking the field and dir attributes from this and creating an orderBy configuration that Breeze understands.

Once we have those values applied, we can execute the query using the EntityManager that was supplied to the DataSource.

Executing a Breeze query

read: function(options){
  // ...

  breezeEntityManager.executeQuery(query).then(function(xhr){
    options.success(xhr.results);
  });
}

Executing a Breeze Query will result in a q.js Promise object, which can be chained in to a then callback that is called when the data finally returns from the server. Once the data has returned, we call options.success and pass the resulting data.

Using the BreezeDataSource

With the read-only BreezeDataSource set up, we can use it as we would any other DataSource for a Kendo UI control. We only need to configure a Breeze EntityManager to work with our API, and then pass that to our BreezeDataSource.

Using the BreezeDataSource

  // create a Breeze EntityManager and configure
  // it for the API that we are connecting to
  var manager = new breeze.EntityManager({
    dataService: new breeze.DataService({
      serviceName: 'data/',
      hasServerMetadata: false
    })
  });

  // create a BreezeDataSource
  var ds = new kendo.data.extensions.BreezeDataSource({
    entityManager: manager,
    endpoint: "products.json",
    pageSize: 10,
    serverPaging: true,
    serverSorting: true
  });

  // assign the DataSource to the grid
  $("#grid").kendoGrid({
    columns: [
      { field: 'ProductName', title: 'Name'},
      { field: 'Supplier.SupplierName', title: 'Supplier'},
      { field: 'Category.CategoryName', title: 'Category' }
    ],
    dataSource: ds,
    pageable: true,
    sortable: true
  });

This will produce a Kendo UI Grid with the data being read through Breeze.js

About the Author
Derick Bailey is a Developer Advocate for Kendo UI, a developer, speaker, trainer, screen-caster and much more. He's been slinging code since the late 80’s and doing it professionally since the mid 90's. These days, Derick spends his time primarily writing javascript with back-end languages of all types, including Ruby, NodeJS, .NET and more. Derick blogs at DerickBailey.LosTechies.com, produces screencasts at WatchMeCode.net, tweets as @derickbailey and provides support and assistance for JavaScript, BackboneJS, MarionetteJS and much more around the web.

11 Comments

  1. 1 pawel 21 Feb 2013
    Please note that Breeze uses q.js for promises, not jquery. By default breeze is configured for knockout.js observables. Do you suggest configuring it for a different library?
     I would like to see how to use kendo ui grid in a real life application based on durandal.js and breeze.
  2. 2 Derick Bailey 21 Feb 2013
    pawel,

    D'oh! I knew that. I updated the post. Thanks :)
  3. 3 Remco Blok 24 Feb 2013

    Hi Derick,

     

    It is great to see Telerik's first post on integration between Kendo UI and Breeze.js. I hope we can see more complex scenarios soon as that is the whole reason for asking for the integration ;-). For simple scenarios we can use Kendo UI’s kendo.data.DataSource and kendo.data.Model classes. For complex scenarios we need Breeze.js.

    I fear though that trying to integrate Kendo UI and Breeze.js at the level of kendo.data.DataSource transport operations will not enable you to maximize the benefits of using Breeze.js. At the transport level you are dealing with JSON data objects. The read transport operation will pass JSON data to the DataSource and it is the DataSource that will create instances of the kendo.data.Model class you defined. The data that the transport create, update and destroy operations get passed in is not those kendo.data.Model instances, but JSON data again, and thus contains no change tracking information on whether an instance is dirty or new.

    I would like to see Kendo UI and Breeze.js integration at the level of entities, not JSON data. And I suspect this does not involve the kendo.data.DataSource or kendo.data.Model classes.

    Kendo’s DataSource can only deal with entities of a single type, does not automatically fixup navigation properties, and its batch support cannot submit changes to instances of different types / multiple DataSources in a single changeset / transaction / unit of work let alone submit the create, update and destroy operations of a single DataSource in a single changeset. It does not act properly as a client cache as a read operation will replace any existing data instead of merging in data.

    Breeze.js EntityManager can deal with entities of multiple types, automatically fixing up their navigation properties, can merge data into its client cache, track changes and submit changes in a single unit of work.

    Breeze.js will also hold all the metadata regarding entity types: how it creates new entities, data properties, key properties, navigation properties, default property values, validation rules, concurrency tokens, etc. Why would you want to duplicate any of this metadata by defining a kendo.data.Model class? I believe through an adapter the Breeze.js EntityManager can make all entities instances of kendo.data.ObservableObject, like it creates knockout observables by default, but surely you don’t need to go through the pain of duplicating the metadata by defining kendo.data.Model classes. I do think Breeze.js needs a tool to generate TypeScript class representations of all entities and their key, data and navigation properties.

    I think the true integration between Kendo UI and Breeze.js would be achieved by making the Kendo UI widgets interact directly with Breeze.js entities and make those widgets understand the change tracking information held in the entity’s EntityAspect and the metadata held in the EntityType. I don’t see a role for the kendo.data.DataSource or kendo.data.Model classes here. For a kendo.ui.Grid to create a new instance it will have ask the view model and the view model will have to ask the Breeze.js EntityManager to create a new instance. When you have a kendo.data.ObservableArray then you can decide in your view model when an entity is removed from the kendo.data.ObservableArray whether you want it removed just from the kendo.data.ObservableArray or whether you also want to flag it for deletion in the EntityManager. When a kendo.ui.Grid column needs to know the type of data (string, number, date) in the column and whether it is editable or not, then I think that needs to be declared on the column, but does not need to be defined in a kendo.data.Model class.

    Of course, this kind of deep integration requires a lot of work and probably goes against Telerik’s design principle in Kendo UI of not taking any dependencies on other libraries. However, I don’t see Telerik matching Breeze.js functionality in their own Kendo UI framework anytime soon either. So what can we expect from Kendo UI and Breeze.js integration in the short and long term?

    Regards,

    Remco

  4. 4 Derick Bailey 25 Feb 2013
    Hi @Remco,

    Thank you for such a great analysis of the current limitations and where you would like to see this heading! This is tremendously valuable to me and the team. We're just beginning to head down this path, and I honestly had no idea that Breeze was able to do so much for us. 

    I can't comment too much on where we are heading at this point, largely because we have not sat down to plan that out yet. This was an initial spike to see get an idea of where we could start and see where we might want to head. We are planning on moving this forward, though, and the information you've provided will be part of the roadmap.
  5. 5 Derick Bailey 05 Mar 2013
    @rgullhaug,

    You may be right about that. This post represents the first experiments that we were travelling through to see what kind of integration is possible, and where it would make sense (if at all).

    Thanks for the feedback on this. We're definitely looking for this kind of info on how we should move forward.
  6. 6 rgullhaug 01 Mar 2013
    Hi,
    When working with breeze I feel the kendo datasource just gets in the way.

    I have limited knowledge of the knockout-kendo project (http://rniemeyer.github.com/knockout-kendo/), so I may be wrong, but it seems like it would be much easier to combine kendo and breeze if you use knockout-kendo.

    As far as I understand you don't use the kendo datasource when you use the knockout kendo bindings -  and therefore is free to use a library like breeze.

    Am I right?
  7. 7 liviu 22 Mar 2013
    Hi! I have an error: 'Microsoft JScript runtime error: 'endPoint' is undefined' (even when i complete it). I'm trying to integrate your code in 'Hot towel' template (with durandal). What should i put in endpoint?
  8. 8 Teeboy 16 Apr 2013
    Hello
    Can you post a solution that includes breeze integration with the above sample + the CRUD operations?
    Thx
  9. 9 Teeboy 16 Apr 2013
    Hello
    Can you post a solution that includes breeze integration with the above sample + the CRUD operations?
    Thx
  10. 10 Derick Bailey 19 Apr 2013
    Hi everyone,

    A quick note - this was the first time i had used Breeze, and I know that the things I did weren't "best practices" with breeze. It was an interesting experiment, though.

    I am looking at getting better integration built, though. We've launched a new KendoUI Labs organization on Github with the intent of providing support for integration projects like Kendo UI & Breeze. 

    If you would like to make suggestions on what should be done, how to do it, send in pull requests or just talk about the integration in general, please head over to:

    https://github.com/kendo-labs/breeze-kendo

    and open an issue or join in a conversation on the issue list.  I'm hoping to get back on to this integration work soon, and will certainly be keeping all of these suggestions in mind when I do.
  11. 11 Rolando 26 Apr 2013
    Hi!
    Thank you for your post.. actually i am using this datasource extension but I am litle stuck trying connect it with a treeView control.. My specific question is how I should pass parameter _FROM_ the treeview control _TO_ the breeze datasource (my treeview control is using loadondemand=true, so that the control should try make request to the service every when a node is expanded).
    if you have time check: http://stackoverflow.com/questions/16225211/kendo-ui-treeview-and-datasource-from-basic-to-spa
    or 
    http://www.telerik.com/account/support-tickets/view-ticket.aspx?threadid=687275

    Thank you!

Comment

  1. Click to add

  2. Click to add

  3. Click to add

  4.    
     
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
    •  
     
      
       
Blogs feed
Categories

  • Tutorials (26)
  • Release (33)
  • Browsers (7)
  • Extensions (3)
  • Tip of the Week (10)
  • Videos (5)
  • Concepts and Theory (13)
  • Misc. (25)
  • Framework Constructs (6)
  • Mobile (6)
  • UI Widgets (5)
  • Blogs (1)
Archive
  • 2013 May (6)
  • 2013 April (10)
  • 2013 March (9)
  • 2013 February (12)
  • 2013 January (10)
  • 2012 December (9)
  • 2012 November (11)
  • 2012 October (6)
  • 2012 September (7)
  • 2012 August (8)
  • 2012 July (10)
  • 2012 June (8)
  • 2012 May (10)
  • 2012 April (7)
  • 2012 March (13)
  • 2012 February (10)
  • 2012 January (6)
  • 2011 December (10)
  • 2011 November (4)
  • 2011 October (6)
  • 2011 September (5)
  • 2011 August (9)
Home Web Mobile DataViz Server Wrappers Whitepapers Surveys Chrome Icenium Contact Us

Kendo UI framework is developed by Telerik - a leading provider of UI components for web, desktop and mobile applications. Trusted by over 100,000 customers worldwide for our devotion to quality and industry-best technical support, Telerik helps professionals maximize their productivity and "deliver more than expected" every day.

kendoui - powered by html5, css3 & jquery
get social
  • Twitter
  • Facebook
  • Google plus
  • RSS
Privacy Policy | Branding Guidelines
Powered by Sitefinity CMS

Copyright © 2011 - 2013 Telerik Inc. All rights reserved.