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
- Part 1: Concepts and Default Features
- Part 2: Creating a REST Service
- Part 3: Creating Your First Grid
- Part 4: Additional Grid Features
- Part 5: Grid Column Features
- Part 6: Reordering Columns
- Part 7: Sorting
- Part 8: Opening Documents
- Part 9: Multi-Row Entries
- Part 10: Full-Text Searching and Field-Specific Filtering
- Part 11: Editable Columns
- Part 12: Highlighting Edited Rows
- Part 13: Create a Dojo EnhancedGrid
- Part 14: Enhanced Filtering with No Coding
- Part 15: Enhanced Printing
- Part 16: Exporting Grid Data
- Part 17: EnhancedGrid Drag and Drop
- Part 18: Context Menus
- Part 19: Pass-Through HTML Content in Grid Columns
- Part 20: Icon Columns
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.
