[CLOSED] How to gridpanel RowSpan ?

  1. #1

    [CLOSED] How to gridpanel RowSpan ?

    hi.

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <ext:ResourceManager runat="server" ShowWarningOnAjaxFailure="false" />
            <ext:Store runat="server" ID="Store1" AutoLoad="true">
                <Model>
                    <ext:Model runat="server">
                        <Fields>
                            <ext:ModelField Name="id" Type="Int" />
                            <ext:ModelField Name="col1" Type="String" />
                            <ext:ModelField Name="col2" Type="String" />
                            <ext:ModelField Name="col3" Type="String" />
                            <ext:ModelField Name="col4" Type="String" />
                            <ext:ModelField Name="col5" Type="String" />
                        </Fields>
                    </ext:Model>
                </Model>
                <Listeners>
                    <Load Handler="
                        //var store = App.Store1;
                        for (var i = 0; i < 10; i++) {
                            store.add({'col1': 'col1_' + i, 'col2': 'col2_' + i, 'col3': 'col3_' + i, 'col4': 'col4_' + i, 'col5': 'col5_' + i});
                        }
                        
                        " />
                </Listeners>
            </ext:Store>
    
            <ext:Viewport runat="server">
                <Items>
                    <ext:Panel runat="server" Region="Center">
                        <Items>
                            <ext:GridPanel runat="server" ID="GridPanel1" StoreID="Store1">
                                <ColumnModel>
                                    <Columns>
                                        <ext:Column runat="server" Text="col1" DataIndex="col1">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col2" DataIndex="col2">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col3" DataIndex="col3">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col4" DataIndex="col4">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col5" DataIndex="col5">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                    </Columns>
                                </ColumnModel>
                                <Plugins>
                                    <ext:CellEditing runat="server" />
                                </Plugins>
                                <View>
                                    <ext:GridView runat="server" />
                                </View>
                                <SelectionModel>
                                    <ext:SpreadsheetSelectionModel ID="SpreadsheetSelectionModel3" runat="server" Mode="Multi" DragSelect="true" RowSelect="true" CellSelect="true" />
                                </SelectionModel>
                            </ext:GridPanel>
                        </Items>
                    </ext:Panel>
                    <ext:Button runat="server" Text="Merge Rows">
                        <Listeners>
                            <Click Handler="
                                var com = App.GridPanel1;
                                var firstCell = com.getView().getCellByPosition({ row: 1, column: 2 });
                                firstCell.dom.rowSpan = 2;
    
                                var cell1 = com.getView().getCellByPosition({ row: 2, column: 2 });
                                Ext.fly(cell1.dom).setStyle('display', 'none'); //or cell1.dom.parentNode.removeChild(cell1.dom);
    
                                var cell2 = com.getView().getCellByPosition({ row: 3, column: 2 });
                                Ext.fly(cell2.dom).setStyle('display', 'none'); //or cell2.dom.parentNode.removeChild(cell2.dom);
                                " />
                        </Listeners>
                    </ext:Button>
                </Items>
            </ext:Viewport>
        </form>
    </body>
    </html>
    RowSpan not working.
    Last edited by fabricio.murta; Apr 20, 2016 at 2:05 PM.
  2. #2
    Hello @siyahgul!

    GridPanels are not really meant to support merging rows like this, so that would not be a trivial change to make this work.

    I've run your test case and I could reproduce the behavior you stated. I'll try to base on this and see if something can be done, will get back to you soon with the outcome!

    Thanks for providing the test case! We really appreciate it!
    Fabrício Murta
    Developer & Support Expert
  3. #3
    hi.
    http://jsfiddle.net/wQSQM/3/
    I suggest you look at this address.
    good work.
  4. #4
    Hello @siyahgul!

    Interesting sample! I see it uses ExtJS 4.2.1, which is equivalent to Ext.NET 2.5.3 if I recall well.

    My reply above was based on the knowledge that there were some samples out there working like that one, but on older ExtJS versions. And even for older ExtJS versions, the official word is that the "rowspan" concept on Grid Panels, since 4.2.1 times, were not really how the gridpanels were meant to work.

    I am pretty confident you will find no implementation of row spanning on gridpanels without a considerable hacking and slashing around the code.

    See these two discussions about implementing this feature to the GridPanel:
    - Sencha forums: How to make a Row span grid with extjs 5 ?.
    This one is for the ExtJS used on Ext.NET 3 series. See how their official response states (politely) that this is not a feature supported for grids.

    - Sencha forums: GridPanel row spanning (well, sort of...)
    And this is a very very old work, upon ExtJS that was part of Ext.NET version 1! Yet, it is left clear that this is but a "sort of" merging of cells, as that's likely not to be a feature the grid panel's designer was thinking about when it was written.

    I hope those two threads clarify a little the situation for you, but in summary:
    - straight out, this is not a supported feature. But I believe you are aware of that and the idea here is try and implement this feature in a way acceptable for your use case.
    - provided the sample you shared, we'll try to see if there's a feasible way to get the grid correctly merging cells, but we can't really guarantee we'll be able to provide that solution.
    - even if we can make something that works for you, it is not likely this feature will get as default feature committed in Ext.NET source base. But I don't think this will be a problem for you, as you are aiming to rely on JavaScript for this, right?

    Please let me have a try to see if I can make this work, but if it turns out too complicated in the current version of ExtJS, we'll let you know. I have some ideas I want to try, but they can just go wrong so, let's see what happens.

    Hope to come back with good news soon! If you have any progress on this to share meanwhile, please don't hesitate to.
    Fabrício Murta
    Developer & Support Expert
  5. #5
    Hello again!

    Here's what I could come up with! Hope it is acceptable. Please bear in mind that this is just "simulating" a row span. The way the grid panel is drawn does not allow real row spanning through cells.

    The code is pretty much yours, except for a slight change in the mock data loading code and also to the actual "merge rows" button on click code.

    <%@ Page Language="C#" %>
    
    <!DOCTYPE html>
    
    <html>
    <head runat="server">
        <title></title>
        <style type="text/css">
            .spanned_cell {
                position: absolute;
                height: 65px;
                width: 100px;
                word-wrap: break-word;
                white-space: pre-wrap;
                background-color: inherit
            }
    
            .whitebg_cell {
                background-color: white;
            }
    
            .recended_cell {
                visibility: hidden
            }
        </style>
        <script type="text/javascript">
            var enableFakeRowSpan = function (item, evnt) {
                var com, i, rowCount, currCell;
                
                com = App.GridPanel1;
                rowCount = com.store.getCount();
    
                // For each cell in odd rows, apply a white-background spanned cell
                for (i = 0; i < rowCount; i += 2 ) {
                    currCell = com.getView().getCellByPosition({ row: i, column: 2 });
                    currCell.addCls('whitebg_cell');
                    currCell.getFirstChild().addCls('spanned_cell');
    
                    // Limitation: height is fixed. At this point, it is possible to fetch
                    // the height of the rows (this and next) and then adjust height of the
                    // "spanned" cell.
                }
    
                // For each cell in even rows apply the recended (unselectable) setting
                // this will avoid being able to "outline" the cell
                for (i = 1; i < rowCount; i += 2) {
                    currCell = com.getView().getCellByPosition({ row: i, column: 2 });
                    currCell.getFirstChild().addCls('recended_cell');
    
                    // Limitation: with keyboard interaction, this cell will still be
                    // "selected" with just the dot-selection control. Ideally the merged
                    // row should be selected but that would also break keyboard navigation,
                    // as if moved left/right once the spanned cell is selected will move
                    // back in the above row.
                }
            }
        </script>
    </head>
    <body>
        <form id="form1" runat="server">
            <ext:ResourceManager runat="server" ShowWarningOnAjaxFailure="false" />
            <ext:Store runat="server" ID="Store1" AutoLoad="true">
                <Model>
                    <ext:Model runat="server">
                        <Fields>
                            <ext:ModelField Name="id" Type="Int" />
                            <ext:ModelField Name="col1" Type="String" />
                            <ext:ModelField Name="col2" Type="String" />
                            <ext:ModelField Name="col3" Type="String" />
                            <ext:ModelField Name="col4" Type="String" />
                            <ext:ModelField Name="col5" Type="String" />
                        </Fields>
                    </ext:Model>
                </Model>
                <Listeners>
                    <% The load handler will leave cells on even columns with no data, as they are not necessary
                       and also will avoid that, by selecting and inspecting selected data, those cells to have
                       value. Alternatively, you may want to just replicate the same data in the cell above to
                       this cell. %>
                    <Load Handler="
                        //var store = App.Store1;
                        for (var i = 0; i < 10; i++) {
                            store.add({
                             'col1': 'col1_' + i,
                             'col2': i%2 == 1 ? '' : 'col2_' + i + ' with long text three lines',
                             'col3': 'col3_' + i,
                             'col4': 'col4_' + i,
                             'col5': 'col5_' + i});
                        }
                        
                        " />
                </Listeners>
            </ext:Store>
    
            <ext:Viewport runat="server">
                <Items>
                    <ext:Panel runat="server" Region="Center">
                        <Items>
                            <ext:GridPanel runat="server" ID="GridPanel1" StoreID="Store1">
                                <ColumnModel>
                                    <Columns>
                                        <ext:Column runat="server" Text="col1" DataIndex="col1">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col2" DataIndex="col2">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col3" DataIndex="col3">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col4" DataIndex="col4">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col5" DataIndex="col5">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                    </Columns>
                                </ColumnModel>
                                <Plugins>
                                    <ext:CellEditing runat="server" />
                                </Plugins>
                                <View>
                                    <ext:GridView runat="server" />
                                </View>
                                <SelectionModel>
                                    <ext:SpreadsheetSelectionModel ID="SpreadsheetSelectionModel3" runat="server" Mode="Multi" DragSelect="true" RowSelect="true" CellSelect="true" />
                                </SelectionModel>
                            </ext:GridPanel>
                        </Items>
                    </ext:Panel>
                    <ext:Button runat="server" Text="Merge Rows">
                        <Listeners>
                            <Click Fn="enableFakeRowSpan" />
                        </Listeners>
                    </ext:Button>
                </Items>
            </ext:Viewport>
        </form>
    </body>
    </html>
    Some CSS code should need review for support in different browsers (like the white-space: on line 14). It was learned from this stackoverflow question: Is there a way to word-wrap long words in a div?.

    As for the reason a simple rowspan does not work it is that the grid is structured like this:
    - HTML div (representing the outer table, the contour or limits of the grid)
     - HTML div (representing the header row of the table)
      - Nested HTML divs (representing each header cell (column tittles)
     - HTML div (representing the grid effective body table with data
      - HTML table (representing the rows -- one table per row)
       - HTML tr + td (each TD representing a column/cell with data of the table)
        - HTML div (where the actual data is imprinted in text)
    Because of that hierarchy, it is helpless to try and change the rowSpan property of the DOM element to make it work as you wanted.

    I hope this helps!
    Fabrício Murta
    Developer & Support Expert
  6. #6
    Hum. I have to try something.
    thank you.
    good working.
    Last edited by siyahgul; Apr 19, 2016 at 4:04 PM.
  7. #7
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <style type="text/css">
            .spanned_cell {
                position: absolute;
                word-wrap: break-word;
                white-space: pre-wrap;
                background-color: inherit;
            }
    
            .whitebg_cell {
                background-color: white;
            }
    
            .recended_cell {
                visibility: hidden;
            }
        </style>
        <script>
            function merge(com) {
                var selected = com.selModel.selected;
    
                if (selected == null) {
                    console.log('Please select...');
                    return;
                }
    
                if (selected.startCell == null || selected.endCell == null) {
                    console.log('Please select...');
                    return;
                }
    
                if (selected.startCell == selected.endCell) {
                    console.log('Please select...');
                    return;
                }
    
                var firstCell;
                var rowHeight = selected.endCell.rowIdx-1;
                var rowWidth = 0;
    
                //rowspan
                for (var row_i = selected.startCell.rowIdx; row_i < selected.endCell.rowIdx + 1; row_i++) {
                    var cell;
                    //colspan
                    for (var cell_i = selected.startCell.colIdx; cell_i < selected.endCell.colIdx + 1; cell_i++) {
                        cell = com.getView().getCellByPosition({ row: row_i, column: cell_i });
                        if (row_i == selected.startCell.rowIdx && cell_i == selected.startCell.colIdx) {
                            //find firstcell
                            firstCell = cell;
                            rowWidth = cell.getWidth();
                        } else if (row_i == selected.startCell.rowIdx && cell_i > selected.startCell.colIdx) {
                            rowWidth += cell.getWidth();
                            cell.addCls('recended_cell');
                        } else {
                            cell.addCls('recended_cell');
                        }
                    }
    
                    rowHeight += cell.getHeight();
                }
    
                firstCell.addCls('whitebg_cell');
                firstCell.getFirstChild().addCls('spanned_cell');
                Ext.fly(firstCell.getFirstChild()).setStyle('width', rowWidth + 'px');
                Ext.fly(firstCell.getFirstChild()).setStyle('height', rowHeight +'px');
            }
        </script>
    </head>
    <body>
        <form id="form1" runat="server">
            <ext:ResourceManager runat="server" ShowWarningOnAjaxFailure="false" />
            <ext:Store runat="server" ID="Store1" AutoLoad="true">
                <Model>
                    <ext:Model runat="server">
                        <Fields>
                            <ext:ModelField Name="id" Type="Int" />
                            <ext:ModelField Name="col1" Type="String" />
                            <ext:ModelField Name="col2" Type="String" />
                            <ext:ModelField Name="col3" Type="String" />
                            <ext:ModelField Name="col4" Type="String" />
                            <ext:ModelField Name="col5" Type="String" />
                        </Fields>
                    </ext:Model>
                </Model>
                <Listeners>
                    <Load Handler="
                        for (var i = 0; i < 10; i++) {
                            store.add({'col1': 'col1_' + i, 'col2': 'col2_' + i, 'col3': 'col3_' + i, 'col4': 'col4_' + i, 'col5': 'col5_' + i});
                        }       
                        " />
                </Listeners>
            </ext:Store>
    
            <ext:Viewport runat="server">
                <Items>
                    <ext:Panel runat="server" Region="Center">
                        <Items>
                            <ext:GridPanel runat="server" ID="GridPanel1" StoreID="Store1">
                                <ColumnModel>
                                    <Columns>
                                        <ext:Column runat="server" Text="col1" DataIndex="col1">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col2" DataIndex="col2">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col3" DataIndex="col3">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col4" DataIndex="col4">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                        <ext:Column runat="server" Text="col5" DataIndex="col5">
                                            <Editor>
                                                <ext:TextField runat="server" />
                                            </Editor>
                                        </ext:Column>
                                    </Columns>
                                </ColumnModel>
                                <Plugins>
                                    <ext:CellEditing runat="server" />
                                </Plugins>
                                <View>
                                    <ext:GridView runat="server" />
                                </View>
                                <SelectionModel>
                                    <ext:SpreadsheetSelectionModel ID="SpreadsheetSelectionModel3" runat="server" Mode="Multi" DragSelect="true" RowSelect="true" CellSelect="true" />
                                </SelectionModel>
                            </ext:GridPanel>
                        </Items>
                    </ext:Panel>
                    <ext:Button runat="server" Text="Merge Colls and Rows">
                        <Listeners>
                            <Click Handler="
                                merge(App.GridPanel1);
                                " />
                        </Listeners>
                    </ext:Button>
                </Items>
            </ext:Viewport>
        </form>
    </body>
    </html>
    thank you for helping.
    last problem editable component width and height percent in firstcell ?
    good working.
    Last edited by siyahgul; Apr 19, 2016 at 10:08 PM.
  8. #8
    Hello!

    There's still a little to go here, but the essence is in using the BeforeEdit event of the editor.

    This should get you started:

    JavaScrit code:
            var handleBeforeEdit = function (item, cellContext) {
                var innerCell, innerWidth, innerHeight,
                    editor, editComponent;
    
                // Actual values on the cell context
                innerCell = cellContext.getCell().getFirstChild();
                innerWidth = innerCell.getWidth();
                innerHeight = innerCell.getHeight();
    
                // Apply them to the editor element
                editor = item.getEditor(cellContext.record, cellContext.column);
                editComponent = editor.getComponent(0);
    
                editComponent.setWidth(innerWidth);
                editComponent.setHeight(innerHeight);
            }
    Listener setup:
    <ext:CellEditing runat="server">
        <Listeners>
            <BeforeEdit Fn="handleBeforeEdit" />
        </Listeners>
    </ext:CellEditing>
    I hope this helps. If you still are stuck with this let us know. This solution is not 100% yet, seems I am having issues with fitting the editor component on full width (height works fine). Must investigate it a little more.
    Fabrício Murta
    Developer & Support Expert
  9. #9
    Hello again!

    Use the listener setup above, but for the scripts, use this:
            var handleBeforeEdit = function (item, cellContext) {
                var innerCell, innerWidth, innerHeight,
                    editor, editComponent;
    
                // Actual values on the cell context
                innerCell = cellContext.getCell().getFirstChild();
                innerWidth = innerCell.getWidth();
                innerHeight = innerCell.getHeight();
    
                // Save the dimensions on the editor object
                editor = item.getEditor(cellContext.record, cellContext.column);
                
                editor.forceWidth = innerWidth;
                editor.forceHeight = innerHeight;
            }
    
            Ext.define('Ext.grid.CellEditor', {
                override: 'Ext.grid.CellEditor',
                startEdit: function (boundEl, value, doFocus) {
                    var innerCell, innerWidth, innerHeight,
                        editor, editComponent;
    
                    this.callParent(arguments);
                    
                    // Apply them to the editor element
                    editor = this;
                    editComponent = editor.getComponent(0);
    
                    if (editor.forceWidth !== undefined && editor.forceHeight !== undefined) {
                        editComponent.setWidth(editor.forceWidth);
                        editComponent.setHeight(editor.forceHeight);
                    }
                }
            });
    There's a forcibly "autofit" to the editor component that gets fired after beforeEdit and also startEdit that couldn't be catched otherwise -- thus the width was always broken.

    This seems to work perfectly setting the editor width height:
    - When it has access to the cell being edited's context (on beforeEdit!) we get the widht/height values and bind somewhere on the editor object.
    - When we are about to start edit and have almost everything done, then we inject the code to resize (again, that would be the third time!) the component to the desired "pseudo" cell dimensions.

    This dual step procedure was only necessary because of the width of the cell. For the height only it wouldn't be necessary and just the previous code were ok.

    I hope this helps!
    Fabrício Murta
    Developer & Support Expert
  10. #10
    hi again.

    My code is running. thank you for helping. I hope that helps others.

    good work.

Similar Threads

  1. [CLOSED] Minor issue on multi rowspan grid
    By cleve in forum 2.x Legacy Premium Help
    Replies: 2
    Last Post: Dec 29, 2012, 6:53 AM
  2. [CLOSED] RowLayout RowSpan problem
    By kenanhancer in forum 1.x Legacy Premium Help
    Replies: 27
    Last Post: Jan 13, 2011, 7:59 AM
  3. [CLOSED] [1.0] Help on Gridpanel Rowspan and Checkbox/Radio
    By MP in forum 1.x Legacy Premium Help
    Replies: 6
    Last Post: Dec 03, 2010, 10:53 AM
  4. [CLOSED] TableLayout cell RowSpan and ColSpan not working in IE7
    By Inoventus in forum 1.x Legacy Premium Help
    Replies: 4
    Last Post: Nov 10, 2010, 3:17 PM

Posting Permissions