jmarkmurphy jmarkmurphy - 1 month ago 26
Javascript Question

jqGrid Treegrid does not expand and collapse rows after dynamic load of data

I have a large bill of materials (BOM) that I have loaded into a jqGrid Treegrid. It has about 500 lines. For various reasons I am trying to keep the data chunks under 64K, so on larger BOMs I am not loading the deepest leaves, for example anything deeper than level 6. I want to dynamically load those when the user selects to expand a node that initially starts out collapsed because it was not loaded. Most everything works as expected. the user can collapse and expand any of the nodes that have been loaded. But, when the user clicks to expand a node with missing children, the server returns all of it's children, and it displays properly in the treegrid. If any of those children have collapsed nodes, the user can expand those an so on to the end of the branch. But that is where the normal behavior stops. Once the user clicks to expand any node with missing children, only the nodes that are included in the most recent server response can be expanded. Nothing can be collapsed. The error that is reported is:

An unexpected error has occurred:
'Unable to get property 'isleaf' of undefined or null reference'
The url is ''
The line number is 92

The source file that the line number refers to is grid.treegrid.js

Here is an example response for expanding a small node with missing children.

{"id":"493","hide":false,"cell":["493","PD M6 X 20","PIN,DOWEL","P","2","2",".00","","$.00","478","7","false","true"]}

The last four values in each row are parent, level, expanded, and isleaf. In this case only row 491 is expandable once the data is loaded, and none of the rows surrounding these three rows, including the parent 478 are collapsible. What do I need to look at to determine the issue? Does loaded have any affect? I am not manually setting loaded on any row. I know which rows have unloaded children when I load the grid. Do I need to manually set that value?

jqGrid (free): 4.4.3

jQuery: 1.9.0

jQuery UI: 1.8.23

Edit: I have upgraded to the following releases:
jqGrid (free): 4.11.1

jQuery: 1.12.4

jQuery UI: 1.10.4

Beyond those versions I run into a problem with require.js which is being loaded, but doesn't seem to play nice with my configuration. I am getting the same errors (though the line number is different) here is the error now:

An unexpected error has occurred:
'Unable to get property 'expanded' of undefined or null reference'
The url is 'http://as400/rui/scripts/jqgrid-4.11.1/js/jquery.jqgrid.min.js?v=5.15b'
The line number is 554

The root of the problem remains the same. While the treegrid data remains visible in the grid, it appears to be invisible to the jqgrid script. the properties of the rows that were there before the load are inaccessible, but the rows that were loaded during the update are indeed available, expandable (once), and are in the correct place in the grid.


Ok, it took a lot of debugging, but I found the answer. The secret sauce lies in the loadonce property of the treegrid. This property must have a value of false in order to allow the treegrid to dynamically load additional nodes. This goes hand in hand with the isleaf property of the row. I found that if the treegrid has loadonce: true, and any rows have isleaf: false and the child nodes are not loaded, then when you expand that child node, all of the local data is deleted and replaced by the child row data, but the grid itself is manipulated properly and becomes out of sync with the local data. loadonce: false suppresses deletion of the local data, and the local data and grid remain in sync.

Maybe this is a bug. If you have loadonce: true, maybe treegrid should suppress posting for additional nodes. Rather than making the grid and local data out of sync.

BTW, I am using the adjacency model for this.