How Many Ways … can a Dojo Grid go wrong?

April 19, 2010

Dojo is a powerful Javascript framework, useful for building browser-based Rich User Interface Applications (RIA). I had some annoying times recently getting a simple Dojo widget to display correctly, so this article captures a few lessons learned in taming that elusive widget. 

In passing I’ll mention that this blog does have a few allusive elements, referencing fine British Acoustic music. The blog title itself refers to the Summer Before the War, a lovely Huw Williams song, and this posting refers to the chorus of  Mike Silver’s beautifiul How Many Rivers.

Project contents

The Javascript I’m dealing with is organised in my Web project as shown here. Dojo itself is in the folder dojoroot and my code is in djna/main.js. I’m also using one data file in the folder djna/datastores.

image

Additionally I have a single HTML file, in my WebContent, which references that javascript. There are three sub-sections, described next.

Note: This article builds from my flawed-original code to the finally working version. The first version you see of a code snippet might need a little enhancement …

Loading Dojo

The first sections sets up a Dojo theme and loads Dojo itself:

  <html>
  <head>
    <title>A Device UI</title>  
    <style type="text/css">
      @import "../dojoroot/dijit/themes/tundra/tundra.css";
    </style>   
    <script type="text/javascript" src="dojoroot/dojo/dojo.js">
    </script>

Initialising the application

Then this code loads the dojo module with my application code in it:

   <script type="text/javascript" > 
      dojo.registerModulePath("djna", "../../djna");
      dojo.require("djna.main");
      dojo.addOnLoad(function(){
          djna.main.startup();                    
      });

Splash screen

As there is a little initialsation to do on applicaiton startup I display a reassuring message, in real-life this might be a nice splash screen.

</head>
   <body class="tundra" id="mainbody">
      <div id="loading"><P>SPLASH</P></div>  
   </body>
  </html>

Javascript Application

My intent is to display a simple grid with some data from the javascript in my datastore. I’m using the Dojo module pattern, where an anonymous function defines the public methods of a “Class”. So my Javascript is also in three parts: the “Class” definition, a main method which sets up the overall display, and utility method that creates the grid.

Class definition

My module outline looks like this, begining with the declaration of the module, which matches the name djna/main.js location of the Javascript file and which was referenced by the 

     dojo.require("djna.main");

statement in the HTML script.

dojo.provide("djna.main");

dojo.require("dojo.parser");
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dojox.grid.DataGrid");
dojo.require("dijit.layout.BorderContainer");

(function(){

     // main goes here

     // grid creationg goes here

})();

Modules referenced by the two metho implementation are made available by the dojo.require statements.

Main entry point

The main function has the responsibility to create a BorderContainer and request the creation of the grid.

       djna.main.startup= function(args) {                
            
            var grid = djna.main.makeGrid();            
                 
            var appContainer = new dijit.layout.BorderContainer({
              style: "width: 230px; height: 320px;  border:solid 1px",
              design: "headline"
            });

            dojo._destroyElement(dojo.byId("loading"));           
            dojo.place(appContainer.domNode, dojo.body(), "first");
            appContainer.addChild(grid);          
            appContainer.startup();                              
      };

The main then positions the grid in the Border Container and replaces the Splash screen with Border Container.

Grid Creation

The grid creation method sets up a data store and layout and then creates the grid

      djna.main.makeGrid = function(){
         var theStore = new dojo.data.ItemFileReadStore(
                  {url:"djna/datastores/dataonly001.json"});
          var layout = {cels: [                         {
                field: ‘custId’, name: ‘Customer Id’                     
            },{
                field: ‘name’, name: ‘Name’              
            },
            {
                field: ‘address’, name: ‘Address’              
            },
            {
                field: ‘postcode’, name: ‘Postcode’              
            }
            ]};
         var grid = new dojox.grid.DataGrid({
                id:"grid",
                store : theStore,
                clientSort : "true",
                structure : layout,
                region: "center"
            });
      };

 

Problems(1) – Drawing a Blank

This all looked (to my eyes) pretty plausible. I loaded the page and got this:

image

An empty box. And no error messages. I was running in Firefox with Firebug enabled. The console showed nothing untoward. So let’s use FireBug’s debugging capabilities. I bring up the Script tab in Firebug, and click the left margin to set breakpoints at the loading of my module:

image

I can now step to the call to djna.main.startup and step inside. Unfortunately, what I see is less than helpful:

image 

The debugging difficuty is caused by Dojo’s implementaiton of modules, using evals. However we can enable debugging.

Enabling Module Debugging

We adjust the Dojo configuration like this:

    <script type="text/javascript" src="dojoroot/dojo/dojo.js"
         djConfig="parseOnLoad: true, debugAtAllCosts: true">
    </script>

Now when we step into the module we can see our code:

image

and as we step through the code to line

     appContainer.addChild(grid);

we see this error:

image

Which suggests that a variable has not been intialised correctly. [The rather hard to understand variable name _17c  is shown because we are not using adevelopment version of Dojo.] A quick examination of the Watch tab shows that the grid variable is undefined:

image

despite the call to

    var grid = djna.main.makeGrid();

and so, we inspect the makeGrid() method more carefully and discover that a line of code is missing:

     var grid = new dojox.grid.DataGrid({
            id:"grid",
            store : theStore,
            clientSort : "true",
            structure : layout,
            region: "center"
        });
    return grid;  // <==== need this
  };

Now when we re-run we don’t see the “undefined” error, but unfortunately, we still see an empty page.

Problem(2) – Lay Me Low

The cause of this problem is a tiny type in the layout. I don’t know how I could have solve this problem efficiently, but in the end I obtained a working example and gradually modified it to match my broken code until I spotted the mistake.

     var layout = {cels: [                         {
                field: ‘custId’, name: ‘Customer Id’                     
            },{

The one letter change to:

     var layout = {cells: [                         {
                field: ‘custId’, name: ‘Customer Id’                     
            },{

gave some progress but yielded another problem …

Problem(3) – Just Got No Style

I’ll admit that solving this one took me an unreasonable amount of time. In retrospect when you see this:

image

it probably should be obvious that this is a style-sheet problem. However things were made a little more difficult by the fact that I had two errors.

Style sheet path

First, a simple path error in the html file:

   <style type="text/css">
      @import "../dojoroot/dijit/themes/tundra/tundra.css";  
    </style>

should be

    <style type="text/css">
      @import "dojoroot/dijit/themes/tundra/tundra.css";  
    </style>

That changes things slightly, but still we have a very similar bad screen:

image 

So there’s a further change:

Extra style sheet

It’s not obvious to a Dojo novice but you need a specific extra style sheet:

<style type="text/css">
@import "dojoroot/dijit/themes/tundra/tundra.css";
@import "dojoroot/dojox/grid/resources/tundraGrid.css";  

</style>

With that in place we can now see the grid taking shape.

image

But strangely, loading never completes, we never see any data. The final problem was probably the most annoying of the lot …

Problem(4) – Too Much Information

I suppose that if I had had the Dojo development source available it might have been possible to figure out what was happening by step-wise debugging. I took the approach of downloading a working example and comparing it with mine. Eventually I saw the error in my data file:

{
    identifier: "name",
    label: "name",
    items: [{
      custId: "123",   
      name: "Arnold Arkwright",
      address: "1, A Avenue; Accrington",
      postcode: "AA1 1AA"
    },{
        custId: "234",   
        name: "Bingley Bradford",
        address: "2, B Bridge; Batley",
        postcode: "BB2 2BB"
    }]
};

Can you see it? Yes, it’s that trailing semi-colon! Remove that and we get:

image

Conclusion

Well, I got there in the end and the journey taught me quite a lot. Seems like the tools such as Firebug do help quite a lot, but there are still quite a few gotchas.

Advertisements

5 Responses to “How Many Ways … can a Dojo Grid go wrong?”

  1. Martin said

    Hi,
    Thank you for publishing your experience with Grids in Widgets.
    It was exactly what I was looking for.

    Greetings,
    Martin

  2. Shyam said

    Thanks for the article.

    Can you pls upload the source for the above article ? It will be of great help.

    Thanks

    Shyam

    • djna said

      I’m sorry that at the moment I just don’t have time to dig out and test the code – I’d hate to post code which I haven’t verified. In fact I think you’ll find that it’s almost all there in the article, certainly all the tricky bits are.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: