Problem Statement
Ext JS grid does not have a direct plugin or component to have grid inside a grid. This functionality will be needed when we want to show the parent and child entity data at a time. For example : We want to show the order line items for an order under each order in an order grid. We can achieve this requirement with the help of Row Expander grid plugin, but still the grid functionality like mouseover, click, column sort, etc would not work.
In this article we will understand the root cause for the issues and learn how to address it.
Getting Started
First get below things in place
- Ext JS application with Ext JS 5.0 or later
Add Child Grid to Parent Grid Row with the help of RowExpander Plugin as explained below:
- Add RowExpander Plugin to parent grid
- Add expandbody event handler for the parent grid
- In expandbody create a child grid instance and render it to the expanded row
With this code you will able to develop a grid as shown below:
You can find a new plugin RowExpanderGrid extended from RowExpander plugin, which can help you add child grid to the row, more easily. It is part of the shared article code.
Now you will notice that on mouseover or click events there are lots of console errors and grid does not behave as it should. Let us see what is causing this issue.
First let us understand how the Grid inside a Grid is rendered using RowExpander plugin. The child Grid is rendered as the child of Grid Row.
Below is the HTML element structure of NestedGrid.
1 2 3 4 5 6 7 |
<table > // Every Grid row is table <tbody> <tr></tr> // All the columns become child td tags under this tr tag <tr> <grid> </tr> // This tr tag is prepared by the RowExpander plugin as row body. The Child grid will be rendered in side this grid. </tbody> </table> |
Because of this structure when mouse events fire on the child grid elements are handled by parent gridview followed by child gridview.
Ext.view.Table is the class responsible for rendering the grid view.processItemEvent is the mouse event handler for the GridView item events., Iitems here are Column Headers , Rows and cells Now, when a mouse events fire on child grid (i.e when the user performs any action with mouse like hovering on the child grid row element,clicking on the child grid row etc..), the processItemEvent handler of the parent grid view is executed first followed by child gridview This handler finds the respective record from the target element and carry out the necessary operations. But, as we know, the element belongs to child grid and scope of function is parent grid. Due to this mismatch the columns and grid records are not found and it throws errors., So, the child grid processItemEvent handler is not being executed.
Let us see how to solve the issue
As discussed, the parent grid processItemEvent handler is being called., Instead, child grid processItemEvent should be called. Our solution should avoid execution of processItemEvent handler of the parent grid. And by doing that, automatically, the child grid processItemEvent handler will be executed.
Following are the solution steps:
- Override Ext.view.Table class -, add a function which will figure out if the event target belongs to the same grid view or not and return the boolean value true indicating the event target belongs to the this gridview and false indicating event target does not belong to this gridview, as shown below
12345678910checkTheContextIsParentGridView: function(e){var target = Ext.get(e.target);var parentGridView = target.up('.x-grid-view');if (this.getId() != parentGridView.getId()) {return false;} else {return true;}} - Override processItemEvent function of Ext.view.Table Class – call the new function, that we implemented in the previous step, by passing the EventObject, call parent function if event target belong same gridview else discard the execution, as shown below.
123456789processItemEvent: function(record, row, rowIndex, e) {if (e.target && !this.checkTheContextIsParentGridView(e)) {return false;} else {return this.callParent([record, row, rowIndex, e]);}}
With this enhancement you will be able to perform all the operation on child grid, including the roweditor for the child grid as shown below:
You may try the code on Sencha Fiddle and let me know how did it go!
Summary
In this article we learned how to solve the issues when we add a grid inside a grid using rowexpander plugin.
References
Ext JS Grid RowExpander plugin doc
Hi Phani,
It’s a cool extension you have made over there and well explained. How is the behaviour on including features and plugins to either of parent or nested grids. Locked columns, summary,filtering and etc?
ExtJS 6.2.0 has got rowWidget Plugin using this we can have nested grid as well.
how we can make this GWT ?
Thanks for this article. Is there a way to make grid selection mutually exclusive. I mean if i select any child grid record, any previously selected record in any other child grid should be cleared and new selection should persists. Same is the case with parent & child, if i select parent row and then click on child the parent row should get dis-selected. Any suggestions would be much appreciated.
Hi Sujay,
AFAIK their is not config available in the frame work to this.. We have to write code for this behavior listening select,selectionchange events on the parent and child grid and deselecting the other grid records.
How can I display a grid inside the the grid column without using any plugin like Row Expander with the parent grid data in same column?
Hello Inamullah,
If i understand correctly, you want to display a grid in one column of the grid instead of displaying the child grid occupying the entire row.
You can try with widget column.
Hello Phani,
I have tried this problem via the widget column , the grid is displaying in the parent grid column but there is a problem that when the child grid will draw in the parent grid then an API will fire for each cell of the parent grid and it will bring some data for child grid to display, but in my case the API is heating and data is also coming for every heat of parent grid cell but displaying the last response of the API in every child grid. Please provide me a way to do this.
Thanks
Inamullah Ansari
Hello Phani,
I have tried it with widget column and grid displaying perfectly but the data is displaying in the grid for the Last response of the API ,
The data is duplicating in the child grid.
Please provide a suggestion to overcome this problem.
Hello Phani,
I tried it through the widget column but the data is coming in the child grid is for the Last API response of the parent grid, and I want the different records in each child grid as per the API response. Please help me in doing this.
Thanks
Inamullah Ansari
Inamullah,
Thanks for showing the interest and glad , we were able to answer few of your questions. To have a elaborated discussion and see how we can benefit you, can you share your email or any mode of contact?
Thanks
Srikar