[OPEN] [#177] Save GridPanel filters and sort within a session

Page 1 of 2 12 LastLast
  1. #1

    [OPEN] [#177] Save GridPanel filters and sort within a session

    Hello,
    I have a GridPanel with remote Filters and Sorts that I want to be able to save. I have actions within the page that has the grid that will navigate the user away from the page, then when they directed back I want to retain/re-apply any filters or sorts they applied. I've been searching the forums and looking at docs but not really found what I'm looking for. I did find that I can get the property Store.Filters which is a DataFilterCollection, but it's read-only so I can't assign it back if I stored it. I know I can individually run through the filters and set them, but I was hoping for an easier 'bulk' solution. Pleas let me know if this is possible.

    Thanks,
    JW
    Last edited by Daniil; Mar 19, 2013 at 1:23 PM. Reason: [OPEN] [#177]
  2. #2
    Hello!

    As I see you that you use Store.Filters. Have you tried to use GridFilters plugin? https://examples2.ext.net/#/GridPane...ilters_Remote/

    However, both of them have Filters collection and you can use AddRange to load 'bulk' of filters.
  3. #3
    Hi Baidaly,
    Yes, sorry I meant GridFilters.Filters, I'm using the plugin. When I go to save the filters, I dig into the GridFilterCollection and I see all the defined filters, what I'm not seeing is the current value of each, is there a different way to get at the values?

    I'll try to come up with a small example page, unfortunately my actual page is huge.
    JW
  4. #4
    Here's an example page of the concept I'm trying to accomplish. You can filter the 'price' column on the grid to say < 90, then click the 'Reload' button on top right which redirects back to itself to simulate leaving and coming back. I want to re-apply the price < 90 filter to the grid when it re-loads, in this example I am capturing the GridFilters1.Filters object into session on the button click event, then in page load trying to set the GridFilters1.Filters object to what is in session. When I debug the code at the point when saving the filter collection in the button click event, I don't see the Value in the numericfilter item, and when the page finishes re-loading No filter is applied. Hopefully this makes sense and I'm not way off-base with what I'm trying to do.

    <%@ Page Language="C#"%>
    <%@ Register Assembly="Ext.NET" Namespace="Ext.Net" TagPrefix="ext" %>
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
                this.Store1.DataSource = this.dynData;
                if (Session["gridFilters"] != null)
                {
                    GridFilters1.Filters.Clear();
                    GridFilters1.Filters.AddRange((GridFilterCollection)Session["gridFilters"]);
                }
            }
        }
        private List<object> dynData
        {
            get
            {
                List<object> comps = new List<object> { };
                
                for (int i = 0; i < 100; i++)
                {
                    comps.Add(new {company = "Company " + i, price = 71.72 + i, change = 0.02, pctChange = 0.03, lastCahnge = new DateTime(2013, 9, 1) });
                }
                
                return comps;
            }
        }
        protected void Store1_RefreshData(object sender, StoreReadDataEventArgs e)
        {
            List<object> data = this.dynData;
            string s = e.Parameters[this.GridFilters1.ParamPrefix];
            //-- start filtering ------------------------------------------------------------
            if (!string.IsNullOrEmpty(s))
            {
                FilterConditions fc = new FilterConditions(s);
    
                foreach (FilterCondition condition in fc.Conditions)
                {
                    Comparison comparison = condition.Comparison;
                    string field = condition.Field;
                    FilterType type = condition.Type;
    
                    object value;
                    switch (condition.Type)
                    {
                        case FilterType.Boolean:
                            value = condition.Value<bool>();
                            break;
                        case FilterType.Date:
                            value = condition.Value<DateTime>();
                            break;
                        case FilterType.List:
                            value = condition.List;
                            break;
                        case FilterType.Numeric:
                            if (data.Count > 0 && data[0].GetType().GetProperty(field).PropertyType == typeof(int))
                            {
                                value = condition.Value<int>();
                            }
                            else
                            {
                                value = condition.Value<double>();
                            }
    
                            break;
                        case FilterType.String:
                            value = condition.Value<string>();
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
    
                    data.RemoveAll(
                        item =>
                        {
                            object oValue = item.GetType().GetProperty(field).GetValue(item, null);
                            IComparable cItem = oValue as IComparable;
    
                            switch (comparison)
                            {
                                case Comparison.Eq:
    
                                    switch (type)
                                    {
                                        case FilterType.List:
                                            return !(value as List<string>).Contains(oValue.ToString());
                                        case FilterType.String:
                                            return !oValue.ToString().StartsWith(value.ToString());
                                        default:
                                            return !cItem.Equals(value);
                                    }
    
                                case Comparison.Gt:
                                    return cItem.CompareTo(value) < 1;
                                case Comparison.Lt:
                                    return cItem.CompareTo(value) > -1;
                                default:
                                    throw new ArgumentOutOfRangeException();
                            }
                        }
                    );
                }
            }
            //-- end filtering ------------------------------------------------------------
            //-- start sorting ------------------------------------------------------------
            if (e.Sort.Length > 0)
            {
                data.Sort(delegate(object x, object y)
                {
                    object a;
                    object b;
    
                    int direction = e.Sort[0].Direction == Ext.Net.SortDirection.DESC ? -1 : 1;
    
                    a = x.GetType().GetProperty(e.Sort[0].Property).GetValue(x, null);
                    b = y.GetType().GetProperty(e.Sort[0].Property).GetValue(y, null);
                    return CaseInsensitiveComparer.Default.Compare(a, b) * direction;
                });
            }
            //-- end sorting ------------------------------------------------------------
            this.GridPanel1.GetStore().DataSource = data;
        }
        protected void btn1_Click(object sender, DirectEventArgs e)
        {
            // Save Filters
            GridFilterCollection myFilters = GridFilters1.Filters;
            Session.Add("gridFilters", myFilters);
            
    
            // Redirect
            Response.Redirect("SaveFilters.aspx");
        }
    </script>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" runat="server">
        <title></title>
        <ext:XScript ID="XScript1" runat="server">
        <script type="text/javascript">
            var template = '<span style="color:{0};">{1}</span>';
            var change = function (value) {
                return Ext.String.format(template, (value > 0) ? "green" : "red", value);
            };
            var pctChange = function (value) {
                return Ext.String.format(template, (value > 0) ? "green" : "red", value + "%");
            };
        </script>
        </ext:XScript>
    </head>
    <body>
        <form id="form1" runat="server">
        <ext:ResourceManager ID="ExtResourceManager" runat="server" DisableViewState="false" RenderStyles="Embedded"></ext:ResourceManager>
        <ext:Button ID="btn1" runat="server" Text="Reload">
            <DirectEvents>
                <Click OnEvent="btn1_Click">
                    <EventMask ShowMask="true"></EventMask>
                </Click>
            </DirectEvents>
        </ext:Button>
        <ext:GridPanel ID="GridPanel1" runat="server" Title="Sample Grid" Width="650" Height="350" EnableColumnMove="false" EmptyText="No rows matching filter criteria.">
            <Store>
                <ext:Store ID="Store1" runat="server" RemoteSort="true" RemoteFilter="true" OnReadData="Store1_RefreshData">
                    <Proxy>
                        <ext:PageProxy/>
                    </Proxy>
                    <Model>
                        <ext:Model ID="Model1" runat="server">
                            <Fields>
                                <ext:ModelField Name="company" />
                                <ext:ModelField Name="price" Type="Float" />
                                <ext:ModelField Name="change" Type="Float" />
                                <ext:ModelField Name="pctChange" Type="Float" />
                                <ext:ModelField Name="lastChange" Type="Date" DateFormat="M/d hh:mmtt" />
                            </Fields>
                        </ext:Model>
                    </Model>
                </ext:Store>
            </Store>
            <ColumnModel OverflowY="Auto">
                <Columns>
                    <ext:RowNumbererColumn Width="50"></ext:RowNumbererColumn>
                    <ext:Column ID="Column1" runat="server" Text="Company" DataIndex="company" Flex="1" />
                    <ext:Column ID="Column2" runat="server" Text="Price" DataIndex="price">                  
                        <Renderer Format="UsMoney" />
                    </ext:Column>
                    <ext:Column ID="Column3" runat="server" Text="Change" DataIndex="change">
                        <Renderer Fn="change" />
                    </ext:Column>
                    <ext:Column ID="Column4" runat="server" Text="Change" DataIndex="pctChange">
                        <Renderer Fn="pctChange" />
                    </ext:Column>
                    <ext:DateColumn ID="DateColumn1" runat="server" Text="Last Updated" DataIndex="lastChange" />
                </Columns>            
            </ColumnModel>       
            <SelectionModel>
                <ext:CheckboxSelectionModel ID="CheckboxSelectionModel1" runat="server" Mode="Single" AllowDeselect="true" ShowHeaderCheckbox="false"></ext:CheckboxSelectionModel>
            </SelectionModel>
            <Features>
                <ext:GridFilters ID="GridFilters1" runat="server" Local="false" Enabled="true">
                    <Filters>
                        <ext:StringFilter DataIndex="company"></ext:StringFilter>
                        <ext:NumericFilter DataIndex="price"></ext:NumericFilter>
                    </Filters>
                </ext:GridFilters>
            </Features>
        </ext:GridPanel>
        </form>
    </body>
    </html>
    Thanks,
    JW
  5. #5
    You should pass filter's values using ExtraParams:

    <ext:Button ID="btn1" runat="server" Text="Reload">
    	<DirectEvents>
    		<Click OnEvent="btn1_Click">
    			<EventMask ShowMask="true"></EventMask>
                <ExtraParams>
                    <ext:Parameter Name="filters" Value="App.GridFilters1.getFilterData()" Mode="Raw" />
                </ExtraParams>
    		</Click>
    	</DirectEvents>
    </ext:Button>
  6. #6
    OK, I'm getting the filters saved in session, but now I'm having trouble applying them after reload. The first time into Page_Load when !IsAjaxRequest I pull my session vars and run through filter/sort routine. But then the OnReadData routine fires and the StoreReadDataEventArgs are empty which I thought should contain the filters and sort I previously applied, so final loaded grid has no filters or sort. Also is there function like 'App.GridFilters1.getFilterData()' to get the current sort order? In code behind tried to get the Store1.Sorters collection, but it's only initial sort which in this example is not set, so for now I hard-coded in button click. Here's my current code, let me know what you think.

    <%@ Page Language="C#"%>
    <%@ Register Assembly="Ext.NET" Namespace="Ext.Net" TagPrefix="ext" %>
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
                this.Store1.DataSource = this.dynData;
                if (Session["gridFilters"] != null && Session["gridSort"] != null)
                {
                    ApplyFilterSort((string)Session["gridFilters"], (DataSorter[])Session["gridSort"]);
                }
            }
        }
        private List<object> dynData
        {
            get
            {
                List<object> comps = new List<object> { };
                
                for (int i = 0; i < 100; i++)
                {
                    comps.Add(new {company = "Company " + i, price = 71.72 + i, change = 0.02, pctChange = 0.03, lastCahnge = new DateTime(2013, 9, 1) });
                }
                
                return comps;
            }
        }
        private void ApplyFilterSort(string filterParms, DataSorter[] gridSort)
        {
            List<object> data = this.dynData;
            //-- start filtering ------------------------------------------------------------
            if (!string.IsNullOrEmpty(filterParms))
            {
                FilterConditions fc = new FilterConditions(filterParms);
    
                foreach (FilterCondition condition in fc.Conditions)
                {
                    Comparison comparison = condition.Comparison;
                    string field = condition.Field;
                    FilterType type = condition.Type;
    
                    object value;
                    switch (condition.Type)
                    {
                        case FilterType.Boolean:
                            value = condition.Value<bool>();
                            break;
                        case FilterType.Date:
                            value = condition.Value<DateTime>();
                            break;
                        case FilterType.List:
                            value = condition.List;
                            break;
                        case FilterType.Numeric:
                            if (data.Count > 0 && data[0].GetType().GetProperty(field).PropertyType == typeof(int))
                            {
                                value = condition.Value<int>();
                            }
                            else
                            {
                                value = condition.Value<double>();
                            }
    
                            break;
                        case FilterType.String:
                            value = condition.Value<string>();
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
    
                    data.RemoveAll(
                        item =>
                        {
                            object oValue = item.GetType().GetProperty(field).GetValue(item, null);
                            IComparable cItem = oValue as IComparable;
    
                            switch (comparison)
                            {
                                case Comparison.Eq:
    
                                    switch (type)
                                    {
                                        case FilterType.List:
                                            return !(value as List<string>).Contains(oValue.ToString());
                                        case FilterType.String:
                                            return !oValue.ToString().StartsWith(value.ToString());
                                        default:
                                            return !cItem.Equals(value);
                                    }
    
                                case Comparison.Gt:
                                    return cItem.CompareTo(value) < 1;
                                case Comparison.Lt:
                                    return cItem.CompareTo(value) > -1;
                                default:
                                    throw new ArgumentOutOfRangeException();
                            }
                        }
                    );
                }
            }
            //-- end filtering ------------------------------------------------------------
            //-- start sorting ------------------------------------------------------------
            if (gridSort.Length > 0)
            {
                data.Sort(delegate(object x, object y)
                {
                    object a;
                    object b;
    
                    int direction = gridSort[0].Direction == Ext.Net.SortDirection.DESC ? -1 : 1;
    
                    a = x.GetType().GetProperty(gridSort[0].Property).GetValue(x, null);
                    b = y.GetType().GetProperty(gridSort[0].Property).GetValue(y, null);
                    return CaseInsensitiveComparer.Default.Compare(a, b) * direction;
                });
            }
            //-- end sorting ------------------------------------------------------------
            this.GridPanel1.GetStore().DataSource = data;
        }
        
        protected void Store1_RefreshData(object sender, StoreReadDataEventArgs e)
        {
            ApplyFilterSort(e.Parameters[this.GridFilters1.ParamPrefix], e.Sort);
        }
        protected void btn1_Click(object sender, DirectEventArgs e)
        {
            // Save Filters
            string myParm = e.ExtraParams["filters"];
            Session.Add("gridFilters", myParm);
            DataSorter mySort = new DataSorter();
            mySort.Property = "price";
            mySort.Direction = Ext.Net.SortDirection.DESC;
            DataSorter[] gridSort = new DataSorter[1];
            gridSort[0] = mySort;
            Session.Add("gridSort", gridSort);
            
            // Redirect
            Response.Redirect("SaveFilters.aspx");
        }
    </script>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" runat="server">
        <title></title>
        <ext:XScript ID="XScript1" runat="server">
        <script type="text/javascript">
            var template = '<span style="color:{0};">{1}</span>';
            var change = function (value) {
                return Ext.String.format(template, (value > 0) ? "green" : "red", value);
            };
            var pctChange = function (value) {
                return Ext.String.format(template, (value > 0) ? "green" : "red", value + "%");
            };
        </script>
        </ext:XScript>
    </head>
    <body>
        <form id="form1" runat="server">
        <ext:ResourceManager ID="ExtResourceManager" runat="server" DisableViewState="false" RenderStyles="Embedded"></ext:ResourceManager>
        <ext:Button ID="btn1" runat="server" Text="Reload">
            <DirectEvents>
                <Click OnEvent="btn1_Click">
                    <EventMask ShowMask="true"></EventMask>
                    <ExtraParams>
                        <ext:Parameter Name="filters" Value="App.GridFilters1.getFilterData()" Mode="Raw" />
                    </ExtraParams>
                </Click>
            </DirectEvents>
        </ext:Button>
        <ext:GridPanel ID="GridPanel1" runat="server" Title="Sample Grid" Width="650" Height="350" EnableColumnMove="false" EmptyText="No rows matching filter criteria.">
            <Store>
                <ext:Store ID="Store1" runat="server" RemoteSort="true" RemoteFilter="true" OnReadData="Store1_RefreshData">
                    <Proxy>
                        <ext:PageProxy/>
                    </Proxy>
                    <Model>
                        <ext:Model ID="Model1" runat="server">
                            <Fields>
                                <ext:ModelField Name="company" />
                                <ext:ModelField Name="price" Type="Float" />
                                <ext:ModelField Name="change" Type="Float" />
                                <ext:ModelField Name="pctChange" Type="Float" />
                                <ext:ModelField Name="lastChange" Type="Date" DateFormat="M/d hh:mmtt" />
                            </Fields>
                        </ext:Model>
                    </Model>
                </ext:Store>
            </Store>
            <ColumnModel OverflowY="Auto">
                <Columns>
                    <ext:RowNumbererColumn Width="50"></ext:RowNumbererColumn>
                    <ext:Column ID="Column1" runat="server" Text="Company" DataIndex="company" Flex="1" />
                    <ext:Column ID="Column2" runat="server" Text="Price" DataIndex="price">                  
                        <Renderer Format="UsMoney" />
                    </ext:Column>
                    <ext:Column ID="Column3" runat="server" Text="Change" DataIndex="change">
                        <Renderer Fn="change" />
                    </ext:Column>
                    <ext:Column ID="Column4" runat="server" Text="Change" DataIndex="pctChange">
                        <Renderer Fn="pctChange" />
                    </ext:Column>
                    <ext:DateColumn ID="DateColumn1" runat="server" Text="Last Updated" DataIndex="lastChange" />
                </Columns>            
            </ColumnModel>       
            <SelectionModel>
                <ext:CheckboxSelectionModel ID="CheckboxSelectionModel1" runat="server" Mode="Single" AllowDeselect="true" ShowHeaderCheckbox="false"></ext:CheckboxSelectionModel>
            </SelectionModel>
            <Features>
                <ext:GridFilters ID="GridFilters1" runat="server" Local="false" Enabled="true">
                    <Filters>
                        <ext:StringFilter DataIndex="company"></ext:StringFilter>
                        <ext:NumericFilter DataIndex="price"></ext:NumericFilter>
                    </Filters>
                </ext:GridFilters>
            </Features>
        </ext:GridPanel>
        </form>
    </body>
    </html>
  7. #7
    Hello,

    A Store has a PageProxy. So, a PageProxy initiates a request to load data into an associated Store.

    So, this code in Page_Load doesn't make sense.
    ApplyFilterSort((string)Session["gridFilters"], (DataSorter[])Session["gridSort"]);
    You should set up initial values for the Filters (Value, GreaterThanValue, etc.).

    Regarding sorters.
    store.getState();
    Generally, there is a very useful Stateful mechanism, but, unfortunately, it doesn't work well with the GridFilters. I am going to report to Sencha.
  8. #8
    The conclusion I'm coming to is that I'm going to have to individually set each GridFilter when I come back to the page with the Grid. I've got the Sort to take by setting the DataSorter and the sort icon is set on the appropiate column header. I also got the store data to filter correctly, but the GridFilter values are not set when I try to 'bulk' set the whole GridFilters object, so you don't get the filter icons or selected values. Thanks for all of your help guys.

    JW
  9. #9
    Quote Originally Posted by jwhitmire36 View Post
    but the GridFilter values are not set when I try to 'bulk' set the whole GridFilters object, so you don't get the filter icons or selected values.
    I think the Filters property doesn't get updated values of filters from a client.

    Also just filtering data doesn't cause updating of filters' UI.

    So, yes, setting up a value for each filter appears to be a single solution in that case.
    Last edited by Daniil; Mar 15, 2013 at 6:48 AM.
  10. #10
    Quote Originally Posted by Daniil View Post
    Generally, there is a very useful Stateful mechanism, but, unfortunately, it doesn't work well with the GridFilters. I am going to report to Sencha.
    Sencha opened a bug.
    http://www.sencha.com/forum/showthread.php?259170

    We created an Issue to track this defect.
    https://github.com/extnet/Ext.NET/issues/177
Page 1 of 2 12 LastLast

Similar Threads

  1. Can I save and after that Reload the filters state in Ext.NET Grid view
    By Nhím Hổ Báo in forum 1.x Help
    Replies: 14
    Last Post: Mar 26, 2015, 10:22 AM
  2. Replies: 8
    Last Post: Dec 21, 2012, 6:42 AM
  3. Replies: 2
    Last Post: Apr 07, 2012, 6:40 AM
  4. Replies: 3
    Last Post: Jan 12, 2012, 3:26 PM
  5. Replies: 4
    Last Post: Jul 25, 2011, 4:57 PM

Posting Permissions