Inside dgrid

What does dgrid mean to Dojo?

dgrid has come to represent and demonstrate the future and power of third-party packages for Dojo. The dgrid package helps to jump-start the repository-centric approach, with parts of DojoX expected to eventually follow suit. It also demonstrates extensive use of the new features and architecture in 1.7 — including granular dependencies, and the new event mechanism in dojo/on — showing how components can use Dojo 1.7 to create amazingly compact and fast user interfaces.

dgrid has also pointed forward to lighter-weight approaches to widget design, more CSS-centric techniques for styling, better separation of structural and skinning styles, and other innovative techniques that have sparked interest into new ways of working with and on Dojo.

Because dgrid builds upon Dojo under the same licensing, you get all of this innovation while preserving Dojo’s clean intellectual property, simple integration with other features, high performance, and professional engineering, taking advantage of the many things that make Dojo excellent.

Why another grid? What about the DojoX Grid and its subclasses (EnhancedGrid, TreeGrid, etc.)?

While the DojoX Grid was cutting edge for its time (initially released as the TurboAjax Grid for Dojo 0.4 in 2006, then converted for and released with Dojo 1.0 in late 2007), browsers have evolved rapidly since then. In fact, Chrome didn’t exist until a year after the DojoX Grid was released. Developers were required to support browsers that greatly limited what could be accomplished on the web.

At the time, innerHTML was often far and away the fastest way to generate a DOM structure; IE6′s DOM methods were (and still are) quite slow. Because of this and the fact that a de facto asynchronous data model for Dojo had not been conceived when the original TurboAjax Grid was written, the DojoX Grid uses a synchronous data rendering model. Although DataGrid does use dojo.data stores, it was implemented as an afterthought, requiring rows to be rendered at least twice for each page of data. In addition, any updates to rows such as row selection, mouseover effects, and data updates caused a row to be completely re-rendered using innerHTML. Using innerHTML also meant that if a developer wanted to change how a row rendered beyond adding CSS classes or inline styles, he or she would need to rewrite significant portions of the string generation methods internal to the DojoX Grid rather than simply modify a DOM node or child nodes.

This reliance on string generation made the DojoX Grid extremely monolithic: because it was so hard to extend, it came with a large number of features built in. Some of the features could be turned off (such as selection and column reordering) or simply not used (sets of columns and sub rows), but the code adding those features to the Grid could not be removed for a lighter build. The developer had access to all of the features of the Grid all of the time, whether he or she wanted them or not.

Because of the nature of rendering using innerHTML using strings and the monolithic approach of the DojoX Grid, extending it meant rewriting large portions of the rendering code to accomplish what you wanted. TreeGrid and EnhancedGrid came along to add trees and other features such as a plugin system, also as afterthoughts. While these new classes added features to the Grid, they were forced to do so via the limited and brittle extension points the Grid already exposed, which meant the new features were brittle as well. At the same time, these new features were only adding to the already large code-base and heavy rendering routines of the Grid.

What was done to avoid those pain points in dgrid?

From the start, dgrid was designed to take advantage of the new asynchronous loader in Dojo 1.7 with granular dependencies; this means it only loads the parts of Dojo that it needs. The “only use what you need” philosophy was very prevalent from the start and led to a very modular (rather than monolithic) design. For instance, if you only need a list of items with no notion of columns at all, the List module alone will give you that.

require(["dgrid/List", "dojo/dom"], function(List, dom){
    var list = new List({
        ...
    }, dom.byId("list"));
});

If your list has hundreds of items in it, you may want to use OnDemandList to fetch and render items from a store as the user scrolls.

require(["dgrid/OnDemandList", "dojo/dom"], function(List, dom){
    var list = new List({
        ...
    }, dom.byId("list"));
});

Adding row selection, cell selection, or keyboard navigation is as simple as mixing in an object that you explicitly require, meaning you only pay for the features you truly need.

require([
    "dojo/_base/declare",
    "dgrid/OnDemandList",
    "dgrid/Selection",
    "dgrid/Keyboard",
    "dojo/dom"
], function(declare, List, Selection, Keyboard, dom){
    var MyList = declare([List, Selection, Keyboard]);
    var list = new MyList({
        ...
    }, dom.byId("list"));
});

With regards to rendering, dgrid was designed to fully rely on DOM-based element creation and manipulation. This gives dgrid the advantage of simple and familiar DOM manipulation when adding or extending features, rather than needing to entirely rewrite portions of the UI using innerHTML.

Events are another area where dgrid greatly improves upon the DojoX Grid components, and furthers the “only pay for what you need” mantra. The dojo/on module, new to Dojo 1.7, can be exercised to its full potential to delegate handlers for only the events that are actually of interest in a particular situation.

dgrid components access data in one of two ways: by passing an array of items to render to the renderArray method, or by providing a store conforming to the Dojo Store API (introduced in Dojo 1.6). Asynchronous data handling was one of the primary concerns of dgrid from the beginning; as a result, it has been designed to natively handle both synchronous and asynchronous data sources.

require([
    "dgrid/OnDemandList",
    "dojo/store/Memory",
    "dojo/dom"
], function(OnDemandList, Memory, dom){
    var dataList = new OnDemandList({
        ...
    });
    dataList.renderArray([ { name: "foo" } ]);

    var storeList = new OnDemandList({
        store: new Memory({
            data: [ { name: "foo" } ]
        })
    });
});

Other key advantages of dgrid include:

  • focus on more maintainable stylesheet-based styling rather than inline styles
  • support for mobile devices
  • accessibility (a11y)
  • robust set of features provided via mixins and plugins (tree, editor, drag and drop, pagination, and more)

It is important to note that dgrid is built to leverage the latest and greatest developments in Dojo, and thus requires Dojo version 1.7.

Similarities to DojoX grids

With the release of the dgrid Beta, now seems an apt time to compare dgrid to the DojoX grids to see what a developer might gain by switching to dgrid.

Firstly, while dgrid and the DojoX grids take different approaches to some things, they do share many similar features in common. The following features are supported by both dgrid and DojoX grids:

  • display, sort, select, and edit in-place thousands of rows of data
  • instantiate and configure via markup
  • directly or indirectly select rows or cells
  • reorder displayed columns using drag and drop
  • virtual paging (progressive loading during scrolling)
  • accessibility
  • internationalization

Differences from DojoX grids

Even with all of these similar features, there are some key areas where dgrid outshines and outperforms the DojoX grids.

Data Handling

DojoX grids all support the Dojo Data API. While this API gives a unified data access pattern, it requires that all property access go through the store which adds extra function calls to an application. In addition, all data fetching was handled through callbacks (including synchronous fetches).

dgrid supports the Dojo Store API. Although it is yet another unified data API, it has some advantages over Dojo Data. First, property access is done as a simple property access on items; this means expensive function calls are not needed to access properties of an item. Second, data fetching routines can return either an immediate object or a promise (or Deferred), depending on whether the operation is synchronous or asynchronous; both of these cases can be handled identically by Dojo’s when function. Third, several store implementations are provided out of the box in Dojo, and moreover, custom implementations are easy to create.

Additionally, dgrid instances have a renderArray method which takes an array of objects and renders them. This can be a very quick way to render a small amount of data without the overhead of instantiating a store.

Drag and Drop

Before the EnhancedGrid, setting up drag and drop for rows in the DojoX grids was an arduous task. Even still, using EnhancedGrid simply for row drag and drop will add a large amount of code on top of DataGrid that may not be needed for a simple list.

dgrid takes a simpler approach: If row drag and drop is needed, simply mix dgrid/extensions/DnD into your dgrid instance constructor and a dojo/dnd/Source will be set up for each instance of the grid. From there, a developer can use the dojo/dnd API to set up drag and drop interaction. This works for both dgrid/List and dgrid/Grid equally: no large subclass of a dgrid class or plugin architecture is needed to use row drag and drop.

Hierarchical Data

One of the most demanded features of the DojoX grid has been hierarchical data display. Out of the box, the base grid provided in DojoX does not support displaying data in a tree; in fact, up until Dojo 1.4, the only way to display a tree-like structure was to use a grid within a grid. Once TreeGrid was introduced, a developer had to switch his or her code to use that constructor while also setting up a hierarchical grid layout. Additionally, a TreeStoreModel was required alongside the store. Since TreeGrid itself extends DataGrid, this means even more code needed to be pulled in for the application, and usage of TreeGrid could prove awkward, especially once any customization was necessary.

Out of the box, dgrid comes with the dgrid/tree column decorator. This means any dgrid instance can display hierarchical data; a developer simply needs to implement the getChildren and mayHaveChildren methods on the store, rather than use a TreeStoreModel.

Pagination

While all of the DojoX grids support virtual paging (progressive rendering of rows as the user scrolls), only EnhancedGrid supports traditional paging (navigating pages of data using buttons). However, all dgrid instances can mix in dgrid/extensions/Pagination to give the user a traditional paging model.

Mobile

None of the DojoX grids have mobile support. In contrast, dgrid was built from the ground up as a mobile-ready widget and supports mobile platforms out of the box.

Conclusion

As you can see, dgrid offers better support out of the box for a variety of features while still keeping your application light. Most features are opt-in and thus only add weight to your application if you specifically include them. By contrast, almost all features of the DojoX grid require a specialized subclass of _Grid which can add features which you may not need in your application.

Be sure to check out our dgrid tutorials to get started with dgrid. If you’d like to migrate your application from the DojoX grids to dgrid, be sure to have a look at the API comparison and usage comparison migration documents.

And as always, SitePen can help you with your migration through either our support services or our development services.