[FIXED] [#689] [3.1.0] GridPanel with ListFilter with store causes error when grid is destroyed

  1. #1

    [FIXED] [#689] [3.1.0] GridPanel with ListFilter with store causes error when grid is destroyed

    Hi,

    If you configure a GridPanel with a column that has a ListFilter where there list filter is populated via a Store (not just a simple options list), then, if the grid is destroyed, an error occurs in the browser console. This only happens if the list filter has not been rendered (which can be quite common as a user doesn't have to use the list filter always).

    Example:

    <%@ Page Language="C#" %>
    
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
                ListFilterStore.DataSource = new object[]
                {
                    new []{ "value1", "display text 1" },
                    new []{ "value2", "display text 2" },
                    new []{ "value3", "display text 3" }
                };
                ListFilterStore.DataBind();
            }
        }
    </script>
    
    <!DOCTYPE html>
    
    <html lang="en">
        <head runat="server">
            <title>Grid filter error when list filter destroyed</title>
        </head>
        <body>
            <ext:ResourceManager runat="server" />
            
            <ext:TabPanel runat="server" Width="400" Height="400">
                <Items>
                    <ext:Panel Title="Explanation" Html="Click on the grid tab. When closing, note the error in browser console" />
                    <ext:GridPanel Title="Grid" runat="server" Closable="true">
                        <Bin>
                            <ext:Store ID="ListFilterStore" runat="server">
                                <Model>
                                    <ext:Model IDProperty="value">
                                        <Fields>
                                            <ext:ModelField Name="value" />
                                            <ext:ModelField Name="displayText" />
                                        </Fields>
                                    </ext:Model>
                                </Model>
                            </ext:Store>
                        </Bin>
                        <Store>
                            <ext:Store ID="Store1" runat="server" PageSize="10">
                                <Model>
                                    <ext:Model runat="server" IDProperty="Id">
                                        <Fields>
                                            <ext:ModelField Name="Id" Type="Int" />
                                            <ext:ModelField Name="Company" Type="String" />
                                            <ext:ModelField Name="Size" Type="String" />
                                            <ext:ModelField Name="Visible" Type="Boolean" />
                                        </Fields>
                                    </ext:Model>
                                </Model>
                                <Sorters>
                                    <ext:DataSorter Property="Company" Direction="ASC" />
                                </Sorters>        
                            </ext:Store>
                        </Store>
                        <ColumnModel runat="server">
                            <Columns>
                                <ext:Column runat="server" Text="ID" DataIndex="Id">
                                    <Filter>
                                        <ext:NumberFilter />
                                    </Filter>
                                </ext:Column>
                                <ext:Column ID="CompanyColumn" runat="server" Text="Company" DataIndex="Company">
                                    <Filter>
                                        <ext:StringFilter />
                                    </Filter>
                                </ext:Column>
                                <ext:Column runat="server" Text="Size" DataIndex="Size">
                                    <Filter>
                                        <ext:ListFilter IDField="value" LabelField="displayText" DataIndex="displayText" StoreID="ListFilterStore" />
                                    </Filter>
                                </ext:Column>
                                <ext:Column runat="server" Text="Visible" DataIndex="Visible" Align="Center">
                                    <Renderer Handler="return (value) ? 'Yes':'No';" />
                                    <Filter>
                                        <ext:BooleanFilter />
                                    </Filter>
                                </ext:Column>
                            </Columns>
                        </ColumnModel>
                        <Plugins>
                            <ext:GridFilters runat="server" />
                        </Plugins>
                    </ext:GridPanel>
                </Items>
            </ext:TabPanel>
        </body>
    </html>
    The above will render a TabPanel.

    If you switch to the tab with the GridPanel, once rendered (there is no data, as not needed for this test), close it straight away, and notice this error in the browser console:

    TypeError: store.un is not a function
        
    store.un('load', me.bindMenuStore, me);
    If you now reload the page and go to the GridPanel tab again, this time actually show the list filter, and then close the tab. Then there is no error.

    The code where the above exception is being raised is in the grid filters list component:

    Ext.define('Ext.grid.filters.filter.List', {
        extend: 'Ext.grid.filters.filter.SingleFilter',
        alias: 'grid.filter.list',
        type: 'list',
    
        ... etc ...
    
        destroy: function() {
            var me = this,
                store = me.store,
                autoStore = me.autoStore;
            
            
            if (store) {
                if (autoStore || store.autoDestroy) {
                    store.destroy();
                } else {
                    store.un('load', me.bindMenuStore, me);
                }
                me.store = null;
            }
    
        ... etc ...
    I guess the grid filter destroy function is only testing if (store) but not whether it is a store id, or an instance of a store.

    Hope that helps?
    Last edited by Daniil; Feb 09, 2015 at 3:14 PM. Reason: [FIXED] [#689] [3.1.0]
  2. #2
    One possible quick fix I think might be this:

    Ext.define('overrides.Ext.grid.filters.filter.List', {
        override: 'Ext.grid.filters.filter.List',
    
        destroy: function() {
            if (typeof this.store === "string") {
                this.callSuper(arguments);
            } else {
                this.callParent(arguments);
            }
        }
    });
    I think this works when you have autoStore as well (which I think is just when a ListFilter is configured with the options property instead).

    Hope that helps?
  3. #3
    Hi Anup,

    Thank you for the report! We will be investigating.
  4. #4
    Created an Issue:
    https://github.com/extnet/Ext.NET/issues/689

    Fixed in the revision 6320 (trunk). It goes to 3.1.0.

    Thank you again for the report and investigation! Much appreciated!

Similar Threads

  1. [CLOSED] Nested Grid ListFilter w/Dynamic Store
    By jwhitmire36 in forum 2.x Premium Help
    Replies: 2
    Last Post: Sep 26, 2014, 4:23 PM
  2. [CLOSED] Update GridFilters ListFilter Store Server-Side
    By jwhitmire36 in forum 2.x Premium Help
    Replies: 2
    Last Post: Dec 23, 2013, 2:44 PM
  3. Replies: 4
    Last Post: Nov 12, 2013, 3:29 PM
  4. [CLOSED] Grid ListFilter
    By watteeuw in forum 2.x Premium Help
    Replies: 9
    Last Post: Sep 12, 2012, 5:36 AM
  5. [CLOSED] SplitCommand shared menu destroyed on store load
    By r_honey in forum 1.x Premium Help
    Replies: 5
    Last Post: Apr 25, 2012, 6:26 PM

Posting Permissions