[CLOSED] How can I filter a GridPanel that has a mapped editor field?

Page 1 of 2 12 LastLast
  1. #1

    [CLOSED] How can I filter a GridPanel that has a mapped editor field?

    I'm trying to setup a GridPanel like the Ext.net example for "Editor Field Mapping".

    Basically, the situation requires a dictionary obj similar to the StoreCombo in the example code.
    Whenever an editable field is constrained by a DB foreign key:
    1. we want this dictionary to hold all valid choices, so anyone making an edit can simply use a dropdown box to pick from them.
    2. And we also want to provide our JS code with a convenient mapping between the value's DB ID and a more user friendly description.

    Similar to this:
    Click image for larger version. 

Name:	Editor Field Mapping.png 
Views:	256 
Size:	36.0 KB 
ID:	24918

    However, our users also need to be able to filter the grid on these mapped editor-fields, like this other ext.net example.
    Click image for larger version. 

Name:	Grid Panel with Local Filtering.jpg 
Views:	490 
Size:	90.8 KB 
ID:	24919

    My understanding is that although we've configured our rendering to display the user-description, the mapped editor field really links to the underlying DB ID. This means the filter actually tries to check the DB ID, which is not helpful to any users.
    Is there a solution to reconfigure our filter to work against the user-descriptions? Client side filtering is our primary concern at the moment.
    Last edited by fabricio.murta; May 17, 2017 at 8:17 PM.
  2. #2
    Hello @Caleb, and welcome to Ext.NET forums!

    Well, in your case what you have on your store for that column is the ID only. So no, there's no way you can filter by the custom-rendered value using the column dropdown's filter. It would require it to be customized in order to somehow build the list of companies (which is probably not on the grid model at all) and try and filter it by applying filters on the store allowing those matching IDs to be displayed.

    What could be just possible would be using the filter header instead and customizing the filter behavior, such as:
    1. the grid model will also include a field to store the chosen department name
    2. it would be also filled when the renderer updates the contents of the cell (so they both have the same value, always)
    3. the filter custom logic applied to the column would instead match that record

    Unfortunately the filter at the header pop-up is not as customizable as the filter header functionality. It can be, yes, but that would be pretty much fiddling with a new functionality and goes beyond the scope here (as a quick and supported solution, at least).

    If you try the described approach above, please start on a simplified code sample so, if you get in trouble trying to develop it, you can provide the code here so we can help you out.

    When/if providing test cases, please follow the guidelines posted here: Tips for creating simplified code samples

    Hope this helps!
    Fabrício Murta
    Developer & Support Expert
  3. #3
    @fabricio.murta, hey thanks for the quick reply over the weekend.
    Will look into the FilterHeader suggestion and see if that's something we can make work. I'll follow up soon.
  4. #4
    Hello @caleb!

    Looking forward to your follow-up. Hope you can make it work the way you need it to. I believe changing the behavior of the filter in the dropdowns will be quite troublesome.
    Fabrício Murta
    Developer & Support Expert
  5. #5
    Ok, so here's what we came up with, which seems to do a pretty good job of satisfying our needs:
    We have a gridpanel, which has a store for whatever business data it has to display
    Because any FK constrained data can get a new value assigned from the user, we decided to keep things safe and simple by tracking only their DB ID on the gridpanel's store.

    Thus the dropdown editor we add to these fields becomes responsible for masking the DB id by using it to figure out the display-description from its own store of valid values defined for that datatype.

    The gridfilter plugin is a better visual and functional fit for us than the filterheader, so we coded a customization for its filter handler (filterFn). This new logic checks a user's filter criteria against the display-description, by translating the DB ID against the lookup store which our dropdown editor originally used.
    However, we couldn't find any obvious property that exposed this filterFn directly. So we got to it by using the more generic CustomConfig property. Is this intentional?

    It'd also be really nice to have our filter dynamically switch between localized vs remote server-side filtering, according to how large our dataset becomes. Is there a way to set this or to otherwise customize the logic? Thanks!
  6. #6
    Hello @caleb!

    I'm not sure what you have done in the page to attain what you want just by your description, if you provide a test case using the custom filter you did, I believe it will be easier to elaborate on an answer, but the CustomConfig is there to allow the user to have flexibility of scenarios that the server-side controls and C# mapping didn't (or couldn't) cover.

    Usually this is not needed unless a customization is intended to a component. Or to overcome a bug when it happens.

    About dynamically switching between local and remote filtering, you could do that if you could determine the amount of data at load time i.e. on Page_Load(). If you want to get deeper on this specific matter I'd ask you to open a new thread so we keep one subject per thread (making it easier to browse for future reference).

    Hope this helps!
    Fabrício Murta
    Developer & Support Expert
  7. #7
    Hi Fabricio,

    Here's the simplified markup code for what we were considering. Please note the question in our in-line comment at line 19 of this:
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="GridPanelTest.aspx.cs" Inherits="_GridPanelTest" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>MultiFeatureGridPanel</title>
        <script>
            var lookupDisplayVal = function (IDValue) {
                var mappingEntry = App.MappingStore.getById(IDValue);
    
                if (Ext.isEmpty(mappingEntry)) {
                    return IDValue;
                }
                return mappingEntry.data.DisplayVal;
            };
    
            var filterFn_DisplayVal = function (gridrow, filterVal) {
                //in a non-hardcoded situation with undetermined number of columns, is there a good way for this filterFn handler to identify which gridview column links to the filterVal?
                var lookupVal = lookupDisplayVal(gridrow.data.FK_ID);
    
                if (Ext.isEmpty(lookupVal)) {
                    return false;
                }
                
                return (lookupVal.toLowerCase().indexOf(filterVal.toLowerCase()) > -1);
            };
        </script>
    </head>
    <body>
        <form runat="server">
            <ext:ResourceManager runat="server" />
    
            <ext:Store ID="MappingStore" runat="server">
                <Model>
                <ext:Model runat="server" IDProperty="IDVal">
                    <Fields>
                        <ext:ModelField Name="IDVal" Type="Int" />
                        <ext:ModelField Name="DisplayVal" Type="String" />
                    </Fields>
                </ext:Model>
                </Model>
            </ext:Store>
    
    
            <ext:GridPanel Title="MultiFeatureGridPanel" ID="MultiFeatureGridPanel" runat="server" Width="650" Height="325">
                <Store>
                <ext:Store ID="BusinessDataStore" runat="server">
                    <Model>
                    <ext:Model runat="server">
                        <Fields>
                            <ext:ModelField Name="businessVal" Type="String" />
                            <ext:ModelField Name="FK_ID" Type="Int" />
                        </Fields>
                    </ext:Model>
                    </Model>
                </ext:Store>
                </Store>
                <ColumnModel runat="server">
                    <Columns>
                        <ext:Column runat="server" Text="ExampleVals" DataIndex="businessVal">
                            <Filter> <ext:StringFilter /> </Filter>
                        </ext:Column>
                            
                        <ext:Column runat="server" Text="Masked FK Editor" DataIndex="FK_ID">
                            <Filter> 
                                <ext:StringFilter>
                                    <CustomConfig>
                                         <ext:ConfigItem Name="filterFn" Value="filterFn_DisplayVal" Mode="Raw" />                                                                              
                                    </CustomConfig>
                                </ext:StringFilter>
                            </Filter>
                            <Renderer Fn="lookupDisplayVal" />
                            <Editor>
                                <ext:ComboBox 
                                    runat="server"
                                    QueryMode="Local"
                                    Editable="true"
                                    StoreID="MappingStore"
                                    DisplayField="DisplayVal"
                                    ValueField="IDVal"
                                    />
                            </Editor>
                        </ext:Column>
                    </Columns>
                </ColumnModel>
                <Plugins>
                    <ext:CellEditing runat="server" />
                    <ext:GridFilters runat="server" />                
                </Plugins>
            </ext:GridPanel>        
    
        </form>
    </body>
    </html>
    And here is the codebehind .cs for it. Please note the observation about exposing filter customization properties on line 37 and 40. Would be really convenient to have something so we don't risk messing things up by using the customConfig, but maybe we missed something? Your input is much appreciated!

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Ext.Net;
    
    public partial class _GridPanelTest : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            MappingStore.DataSource = new object[] 
            {
                new object[] {0, "Some"},
                new object[] {1, "Something"},            
                new object[] {2, "Somehow"},
                new object[] {3, "Someway"},
                new object[] {4, "Someone"},            
            };
            MappingStore.DataBind();
    
            BusinessDataStore.DataSource = new object[]
            {
                new object[] {"Record A: Some", 0},
                new object[] {"Record B: Something", 1},
                new object[] {"Record C: Some", 0},
                new object[] {"Record D: Something", 1},
                new object[] {"Record E: Somehow", 2},
                new object[] {"Record F: Some", 0}
            };
            BusinessDataStore.DataBind();
    
            //access the 2nd column's filter(s)
            GridFilterCollection maskedFilters = MultiFeatureGridPanel.ColumnModel.Columns[1].Filter;
    
            //convert first one into an expicit StringFilter. Doesn't seem to expose any properties to have it filter against our drop down editor's rendered val
            StringFilter convertedSF = (StringFilter)maskedFilters[0];        
    
            //as an abstract GridFilter,  doesn't seem to expose such a property either
            GridFilter abstractFilter = maskedFilters[0];                                       
        }
    
    }
  8. #8
    Hello @Caleb!

    Impressive! Thanks for the simple case, we're looking after the issue to advice you about the filter customization. Just wanted to leave you an useful tip for providing complete test cases with code behind, yet all in just one code block. Easier for both test after change -- no rebuild necessary -- and also easier to copy+paste+run if we exchange versions of the reviewed test case.

    <%@ Page Language="C#" %>
    
    <!DOCTYPE html>
    
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            MappingStore.DataSource = new object[] 
            {
                new object[] {0, "Some"},
                new object[] {1, "Something"},            
                new object[] {2, "Somehow"},
                new object[] {3, "Someway"},
                new object[] {4, "Someone"},            
            };
            MappingStore.DataBind();
    
            BusinessDataStore.DataSource = new object[]
            {
                new object[] {"Record A: Some", 0},
                new object[] {"Record B: Something", 1},
                new object[] {"Record C: Some", 0},
                new object[] {"Record D: Something", 1},
                new object[] {"Record E: Somehow", 2},
                new object[] {"Record F: Some", 0}
            };
            BusinessDataStore.DataBind();
    
            //access the 2nd column's filter(s)
            GridFilterCollection maskedFilters = MultiFeatureGridPanel.ColumnModel.Columns[1].Filter;
    
            //convert first one into an expicit StringFilter. Doesn't seem to expose any properties to have it filter against our drop down editor's rendered val
            StringFilter convertedSF = (StringFilter)maskedFilters[0];        
    
            //as an abstract GridFilter,  doesn't seem to expose such a property either
            GridFilter abstractFilter = maskedFilters[0];                                       
        }
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>61872 - Custom header dropdown filter (user provided)</title>
        <script type="text/javascript">
            var lookupDisplayVal = function (IDValue) {
                var mappingEntry = App.MappingStore.getById(IDValue);
    
                if (Ext.isEmpty(mappingEntry)) {
                    return IDValue;
                }
                return mappingEntry.data.DisplayVal;
            };
    
            var filterFn_DisplayVal = function (gridrow, filterVal) {
                //in a non-hardcoded situation with undetermined number of columns, is there a good way for this filterFn handler to identify which gridview column links to the filterVal?
                var lookupVal = lookupDisplayVal(gridrow.data.FK_ID);
    
                if (Ext.isEmpty(lookupVal)) {
                    return false;
                }
    
                return (lookupVal.toLowerCase().indexOf(filterVal.toLowerCase()) > -1);
            };
        </script>
    </head>
    <body>
        <form runat="server">
            <ext:ResourceManager runat="server" />
    
            <ext:Store ID="MappingStore" runat="server">
                <Model>
                <ext:Model runat="server" IDProperty="IDVal">
                    <Fields>
                        <ext:ModelField Name="IDVal" Type="Int" />
                        <ext:ModelField Name="DisplayVal" Type="String" />
                    </Fields>
                </ext:Model>
                </Model>
            </ext:Store>
    
    
            <ext:GridPanel Title="MultiFeatureGridPanel" ID="MultiFeatureGridPanel" runat="server" Width="650" Height="325">
                <Store>
                <ext:Store ID="BusinessDataStore" runat="server">
                    <Model>
                    <ext:Model runat="server">
                        <Fields>
                            <ext:ModelField Name="businessVal" Type="String" />
                            <ext:ModelField Name="FK_ID" Type="Int" />
                        </Fields>
                    </ext:Model>
                    </Model>
                </ext:Store>
                </Store>
                <ColumnModel runat="server">
                    <Columns>
                        <ext:Column runat="server" Text="ExampleVals" DataIndex="businessVal">
                            <Filter> <ext:StringFilter /> </Filter>
                        </ext:Column>
                            
                        <ext:Column runat="server" Text="Masked FK Editor" DataIndex="FK_ID">
                            <Filter> 
                                <ext:StringFilter>
                                    <CustomConfig>
                                         <ext:ConfigItem Name="filterFn" Value="filterFn_DisplayVal" Mode="Raw" />                                                                              
                                    </CustomConfig>
                                </ext:StringFilter>
                            </Filter>
                            <Renderer Fn="lookupDisplayVal" />
                            <Editor>
                                <ext:ComboBox 
                                    runat="server"
                                    QueryMode="Local"
                                    Editable="true"
                                    StoreID="MappingStore"
                                    DisplayField="DisplayVal"
                                    ValueField="IDVal"
                                    />
                            </Editor>
                        </ext:Column>
                    </Columns>
                </ColumnModel>
                <Plugins>
                    <ext:CellEditing runat="server" />
                    <ext:GridFilters runat="server" />                
                </Plugins>
            </ext:GridPanel>        
    
        </form>
    </body>
    </html>
    Fabrício Murta
    Developer & Support Expert
  9. #9
    Hello again!

    You are using a feature that is not documented even as a protected/private feature in ExtJS. I dare say this "works by accident" but it really looks like a nice way to customize a filter.

    So, according to ExtJS documentation on the gridfilters' string filter, we can't really support this on Ext.NET, simply cause it is not guaranteed nor supported through versions of ExtJS.

    May be confusing to understand the claim, as the feature is there, but here's an example of ExtJS claim on private classes: Documentation on Ext.grid.CellEditor for ExtJS 6.2.1.

    That said, I'm afraid you should rely on the approach you taken. This you have done could be seen as extending the grid String filter class, as using a "custom filter" for a "string filter" is pretty much not using the "string filter" itself.

    At the same time, contradicting myself, you shouldn't rely on that to be working over different versions of Ext.NET. As a non-documented feature, it is bound to be changed without prior notice nor any breaking change document (which we make considerable efforts to maintain and avoid -- when documented and supported feature).

    Bottomline, I'd say, use the alternative you found. It works fine, but you'll probably want to leave some comments to review it whenever a version upgrade is made. There's no such "feature" of specifying the filter function unless you extend both Ext.NET and ExtJS (extending basically the Ext.grid.filters.filter's Base or SingleFilter abstract classes from ExtJS). The alternative you are using is the shortest path to what you need.

    Hope this helps!
    Fabrício Murta
    Developer & Support Expert
  10. #10
    Hello @Caleb!

    Been some time since we last replied you here and still no feedback from you. Do you still need help on this matter?

    We may mark this as closed if you don't reply in 7+ days. But don't worry, this will not prevent you from posting more follow-ups when you feel convenient.
    Fabrício Murta
    Developer & Support Expert
Page 1 of 2 12 LastLast

Similar Threads

  1. [CLOSED] GridPanel Editor Field Mapping
    By Alaswad in forum 3.x Legacy Premium Help
    Replies: 5
    Last Post: Jan 19, 2016, 8:57 AM
  2. Replies: 0
    Last Post: Jun 12, 2014, 5:30 AM
  3. GridPanel Editor field help
    By venu.sn2009 in forum 1.x Help
    Replies: 2
    Last Post: Jul 14, 2011, 8:20 AM
  4. Replies: 4
    Last Post: Jul 01, 2011, 5:05 PM
  5. [CLOSED] GridPanel Editor field mapping problem
    By kenanhancer in forum 1.x Legacy Premium Help
    Replies: 7
    Last Post: Mar 01, 2011, 7:42 AM

Tags for this Thread

Posting Permissions