Dojo Data Grid – Part 21: Locking Columns

In a recent post, Mark Roden showed how to horizontally lock columns in an ExtJS grid, which has the same effect as Freeze Panes in Excel. In this post, I’ll show how to achieve the same functionality with the Dojo DataGrid.

Dojo Data Grid Series

LockedCols_A

When the grid has locked columns, a horizontal scroll bar will appear to scroll unlocked columns when there isn’t enough screen real estate to display all of the columns. In the screen shot above, the first two columns are locked and the rest will scroll.

Based on the Dojo DataGrid documentation this seems like it should be a relatively easy feature to implement. With a declaratively-or programmatically-defined grid, it’s pretty simple. Unfortunately, I don’t see a way to make it work with the Dojo Data Grid control in XPages.

Declarative Definition

In a declaratively-defined grid, you add colgroup tags before the tags defining the grid columns. For example, if you have a 6-column grid and you want to freeze the first column, you’d add this before the thead tag in the grid definition:

<colgroup colspan="1" noscroll="true"></colgroup>
<colgroup colspan="5"></colspan> 

Programmatic Definition

You can implement the same effect in a programmatically-defined grid by modifying the structure property to list two groups of cells (one set to freeze and one set to scroll), rather than just defining the grid rows.

An example of this method will be shown in the solution below.

Problem with the Dojo Data Grid Control

Unfortunately, there doesn’t appear to be a way to modify the output of the Dojo Data Grid control in a similar manner. I tried adding colgroup tags within the grid tag but before the column tags, but the colgroup tags were not rendered. I also tried other methods of running client-side javascript after the page loads to insert the tags and re-draw the grid, but none of it was effective.

The Solution – Programmtically Define the Grid

So, for the time being, the way to implement column locking in the grid is to programmatically declare your grid instead of using the Dojo Data Grid control.

It’s not as complicated as it might sound, but it’s definitely more work than using the grid control.

Here is the source of the entire page that generated the grid shown in the screen shot above.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
  xmlns:xe="http://www.ibm.com/xsp/coreex" dojoParseOnLoad="true"
  dojoTheme="true">

  <xe:restService id="restJsonService" pathInfo="gridData">
    <xe:this.service>
      <xe:viewItemFileService defaultColumns="true"
        var="gridEntry" viewName="ByName-First" count="10000">
      </xe:viewItemFileService>
    </xe:this.service>
  </xe:restService>

  <xp:this.resources>
    <xp:dojoModule name="dojox.grid.DataGrid"></xp:dojoModule>
    <xp:dojoModule name="dojo.data.ItemFileWriteStore"></xp:dojoModule>

    <xp:styleSheet
      href="/.ibmxspres/dojoroot/dojox/grid/resources/tundraGrid.css">
    </xp:styleSheet>
  </xp:this.resources>
	
  <xp:eventHandler event="onClientLoad" submit="false">
    <xp:this.script><![CDATA[		
      var jsonStore = new dojo.data.ItemFileWriteStore({ url: "Grid_21_LockColumns.xsp/gridData"});

      var layout = [
        {cells:[ [ 
          {field:'firstname', name:'First',width:'8em'}, 
          {field:'lastname', name:'Last', width:'10em'}
          ] ], noscroll:true 
        }, 
        {cells:[ [ 
          {field:'address', name:'Address',width:'18em'},
          {field:'city', name:'City',width:'10em'},
          {field:'state', name:'State',width:'5em'},
          {field:'zip', name:'Zip',width:'7em'}
          ] ] 
        }
      ];
	
      grid = new dojox.grid.DataGrid({
        store: jsonStore,
        structure: layout,
        rowsPerPage: 25,
        autoHeight: 15
      }, '#{id:gridNode}');

      grid.startup();
    ]]></xp:this.script>
  </xp:eventHandler>

  <xp:div id="gridNode"></xp:div>

</xp:view>

Lines 3 and 4 show the two dojo properties that need to be set at the page level. Since we’re not using the Dojo Data Grid control, we have to set these properties manually.

Lines 6-12 define the REST service that provides the data for the grid

Lines 14-21 include the resources required. This generally isn’t required when using the grid control, because some resources are automatically included by the control.

Lines 23-51 include the code that defines the grid. The code runs on the page’s onclientload event.

  • Line 25 sets up the data store for the grid. It reads data from the REST service on the same page.
  • Lines 27-40 define the grid structure. The first group of cells has the noscroll attribute set to true. This locks the columns in place.
  • Lines 42-47 create the grid and set the key properties
  • Line 49 generates the grid.

Disclaimer

This is a proof-of-concept to show the column locking feature. I realize that creating the REST service and setting its count to a high number to include all records while also not using a RESTful data store defeats the purpose of lazy loading. However, I had issues getting the REST data store to display data in the grid.

Advertisements

8 responses to “Dojo Data Grid – Part 21: Locking Columns”

  1. Sushant Bangalorkar says :

    Hi, How can I save the changes I make to this type of grid if I have editable cells . I want to make changes to reflect to datastore . I tried using :
    var st=dijit.byId(“grid”).store;
    var args = {
    onComplete: function() { alert(“done”) },
    onError: function() { alert(‘Update error’); }
    }
    st.save(args);
    Could tell me how to bind the store with grid and get handle to rest service . I get errors like . store undefined or restservice undefined .

    Thanks …

    • Brad Balassaitis says :

      I haven’t tried saving changes with this type of grid, but the first thing I would try is to use the same logic used on the other editable grids with REST services, which is .save(). In the above example, it would be restJsonService.save();

      If you’re going through the REST service to get the data store, make sure that the dijit.byId() method is getting a handle to the appropriate element. In the example above, the grid’s id is: gridNode

      To be sure whether you’re getting a handle on the grid itself, try this:

      var st=dijit.byId(“grid”).
      if (st) {
      alert(‘found grid’);
      } else {
      alert(‘did not find grid’);
      }

      Assuming that part is fine, I would think the focus should be on calling save() on the REST service directly. Maybe there’s a quirk with going through a declaratively-defined grid with an XPages REST service as the data store. Or, maybe there’s a disconnect that won’t let it work at all with that configuration. Let me know if this helps.

  2. juliocbb says :

    I’m using dojox.grid.EnhancedGrid.
    in dojo 1.8-
    in which I create a grid with two input.
       and utilzo this code with a button to generate a new line that has two input.
       dijit.byId grid2 var = (‘grid’);
        grid2.store.newItem ({tmHoraInicio:”, tmHoraTermino:”});

    with this every time I press the button it generates a new line with two input.
    all good.

    the problem happens when I write on these inputs.
    and I press the button to generate a new line.
    everything that was written in input lets me clean.

  3. juliocbb says :

    I’m using lazytreegrid.
    and I want to export it to a csv, then create an excel.

    • Brad Balassaitis says :

      I haven’t used the lazytreegrid, but, as an extension of the TreeGrid, I’m not aware of a way to export it. The exporting functionality that I’ve used is part of the EnhancedGrid, but that’s separate from the TreeGrid.

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: