[FIXED] [#1263] [2.5.3] View refreshNode

  1. #1

    [FIXED] [#1263] [2.5.3] View refreshNode

    I have a grid and I can call the following from javascript and everything works fine:

    row = App.AnalysisBuckets.getSelectionModel().getLastSelected();
    // Update some fields row.data.Open = 5
    App.AnalysisBuckets.getView().refreshNode(row.index);
    But when ext:Grid has an ext:Grouping feature and a group above the selection is collapsed refreshNode no longer works.

    Any thoughts?
    Last edited by fabricio.murta; Feb 20, 2016 at 12:59 AM.
  2. #2
    Here is a code sample.

    After launching the sample.
    • Select a row in the February 2016 grouping and press the "Increment Row" button. GOOD
    • Collapse the first group, March 2016, and press the "Increment Row" button. ERROR
    • Expand the first group, March 2016, and press the "Increment Row" button. GOOD
    • Select a row in the March 2016 grouping and press the "Increment Row" button. GOOD
    • Collapse the second group, February 2016, and press the "Increment Row" button. GOOD


    <%@ Page Language="C#" %>
    
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
                DateTime today = DateTime.Today;
                DateTime later = DateTime.Today.AddMonths(1);
    
                Store store = this.GridPanel1.GetStore();
                store.DataSource = new object[] 
                { 
                    new object[] { today.AddHours(1), 1},
                    new object[] { today.AddHours(2), 11 },
                    new object[] { today.AddHours(3), 111 },
                    new object[] { later.AddHours(1), 2 },
                    new object[] { later.AddHours(2), 22 },
                    new object[] { later.AddHours(3), 222 }
                };
            }
        }
    </script>
    
    <!DOCTYPE html>
    
    <html>
    <head runat="server">
        <title>Ext.NET v2 Example</title>
    
        <script>
    
            Ext.grid.feature.Grouping.override({
                pruneGroupedHeader: function () {
                    var me = this,
                        header = me.getGroupedHeader();
    
                    if (me.hideGroupedHeader && header) {
                        Ext.suspendLayouts();
                        if (me.prunedHeader && me.prunedHeader !== header) {
                            me.prunedHeader.show();
                        }
                        me.prunedHeader = header;
                        if (!header.showWhenGrouped) header.hide();
                        Ext.resumeLayouts(true);
                    }
                }
            });
    
            var getGroupString = function getGroupString(rec) {
                return Ext.Date.format(rec.get('datetime'), 'F Y');
            };
    
            var group = function (groupers, direction) {
                var grouper;
    
                if (Ext.isString(groupers) && (groupers === "datetime")) {
                    grouper = this.groupers.get(groupers);
    
                    if (!grouper) { // If it is not currently grouped by the datetime field
                        groupers = {
                            direction: "DESC",
                            property: "datetime",
                            getGroupString: getGroupString
                        }
                    }
                }
    
                Ext.data.Store.prototype.group.apply(this, [groupers, direction]);
            };
        </script>
    </head>
    <body>
        <form runat="server">
            <ext:ResourceManager runat="server" />
    
            <ext:GridPanel ID="GridPanel1" runat="server" ClientIDMode="Static">
                <HtmlBin>
                    <script type="text/javascript">
                        var incrementRow = function () {
                            debugger;
                            var row = App.GridPanel1.getSelectionModel().getLastSelected();
    
                            row.data.test1 = row.data.test1 + 1;
                            App.GridPanel1.getView().refreshNode(row.index);
                        }
                    </script>
                </HtmlBin>
                <Store>
                    <ext:Store runat="server">
                        <Model>
                            <ext:Model runat="server">
                                <Fields>
                                    <ext:ModelField Name="datetime" Type="Date" />
                                    <ext:ModelField Name="test1" Type="Int" />
                               </Fields>
                            </ext:Model>
                        </Model>
                        <Groupers>
                            <ext:DataSorter Property="datetime" Direction="DESC">
                                <CustomConfig>
                                    <ext:ConfigItem Name="getGroupString" Value="getGroupString" Mode="Raw" />
                                </CustomConfig>
                            </ext:DataSorter>
                        </Groupers>
                        <CustomConfig>
                            <ext:ConfigItem Name="group" Value="group" Mode="Raw" />
                        </CustomConfig>
                    </ext:Store>
                </Store>
                <ColumnModel runat="server">
                    <Columns>
                        <ext:DateColumn ID="DT" runat="server" Text="DateTime" DataIndex="datetime" Format="yyyy-MM-dd hh:mm"
                            showWhenGrouped="true" />
                        <ext:Column runat="server" Text="Test1" DataIndex="test1" />
                   </Columns>
                </ColumnModel>
                <SelectionModel>
                    <ext:RowSelectionModel runat="server">
                        <Listeners>
                            <SelectionChange Handler="App.BtnIncrement.setDisabled(App.GridPanel1.getSelectionModel().getCount( ) == 0);" />
                        </Listeners>
                    </ext:RowSelectionModel>
                </SelectionModel>
                <Features>
                    <ext:Grouping ID="Grouper" runat="server" HideGroupedHeader="true" />
                </Features>
                <Listeners>
                    <AfterLayout Handler="#{DT}.show()" />
                </Listeners>
                <BottomBar>
                    <ext:Toolbar runat="server">
    
                        <Items>
                            <ext:Button ID="BtnIncrement" runat="server" ClientIDMode="Static" Text="Increment Row" Flat="false"
                                Disabled="true">
                                <Listeners>
                                    <Click Handler="incrementRow()" />
                                </Listeners>
                            </ext:Button>
                        </Items>
                    </ext:Toolbar>
                </BottomBar>
            </ext:GridPanel>
        </form>
    </body>
    </html>
  3. #3
    Hello Chris!

    First of all, thanks for the awesome test case! I could reproduce the issue here at once!

    Now, as for the problem, it is because you are relying on the row.index to update the row. When you collapse the group, it becomes to the view's dataSource point of view, no longer a 1:1 mapping between the store and view data. A collapsed group becomes a single row in the view, and the hidden rows are out of the list until it is expanded again.

    This is a bug, and there has been a related bug that was fixed on ExtJS 5.2, which is now part of Ext.NET 3.3 and Ext.NET 4. There's a good chance this issue has been addressed for these versions as well, but I won't dig in further.

    As for the solution, you have to get the actual row position in the view's data. This hopefully will work for you too. Replace your incrementRow function by this:
    var incrementRow = function () {
        var row = App.GridPanel1.getSelectionModel().getLastSelected();
    
        row.data.test1 = row.data.test1 + 1;
    
        var key = row.internalId;
    
        var rowIndex;
    
        var gridView = App.GridPanel1.getView();
    
        var keys = gridView.dataSource.data.keys;
        for (var idx in keys) {
            if (keys[idx] == key) {
                rowIndex = idx;
                break;
            }
        }
    
        if (rowIndex != null) {
            App.GridPanel1.getView().refreshNode(rowIndex);
        }
    }
    And you should be up to speed on that issue. This wil ensure the row you are asking to be refreshed actually exists. The if in the bottom is very unlikely to be false, ever (it can be false if you can collapse the rows between getting the last selected row and the datasource's keys).

    I hope this helps!
    Fabrício Murta
    Developer & Support Expert
  4. #4
    Since I call refreshNode in several places I was hoping for an official override of the function instead of a work around. I don't have access to SVN at work to see any code changes in Ext.net 3 or 4. I will write my on override unless you can suggest one.
  5. #5
    Hello Chris!

    Current Ext.NET versions support providing the entire record object to the refreshNode() function.

    It seems you can use the new ExtJS's version of the refreshNode() function with no issues.

    Ext.define('Ext.view.AbstractView', {
        override: 'Ext.view.AbstractView',
        refreshNode: function (record) {
            if (Ext.isNumber(record)) {
                record = this.store.getAt(record);
            }
            this.onUpdate(this.dataSource, record);
        }
    });
    Or you can simply use this if you are not ever going to send as a record:
    Ext.define('Ext.view.AbstractView', {
        override: 'Ext.view.AbstractView',
        refreshNode: function (index) {
            this.onUpdate(this.dataSource, this.store.getAt(index));
        }
    });
    I will ask Daniil how should we deal with this fix in ExtJS 2 svn branch and update here.
    Fabrício Murta
    Developer & Support Expert
  6. #6
    Thanks for the overrides. I decided on the current Ext.NET version that supports providing the entire record object to the refreshNode()function. Everything seems to work just fine now.


    Ext.define('Ext.view.AbstractView', {
        override: 'Ext.view.AbstractView',
        refreshNode: function (record) {
            if (Ext.isNumber(record)) {
                record = this.store.getAt(record);
            }
            this.onUpdate(this.dataSource, record);
        }
    });
  7. #7
    Alright Chris! Sorry for the delay! I had to confirm some things with @Daniil before I proceeded to the fix.

    It turned out to be a good fix after all, and it was just applied to the current SVN tree. The revision 6747 contemplates this change.

    Thank you very much for raising this issue!
    Fabrício Murta
    Developer & Support Expert

Similar Threads

  1. Replies: 0
    Last Post: Dec 17, 2013, 6:17 AM
  2. Replies: 7
    Last Post: Mar 27, 2013, 6:07 AM
  3. Replies: 1
    Last Post: Feb 01, 2012, 2:35 PM
  4. Replies: 2
    Last Post: Jan 10, 2012, 6:35 AM
  5. Switch from tree view to accordian view?
    By jaydwire2 in forum 1.x Help
    Replies: 1
    Last Post: Sep 18, 2009, 4:31 PM

Posting Permissions