Use screen filter programmatically from function

Using Ext.ux.grid.FiltersFeature, I have remote filters, and I'm trying to write a function to apply a date filter in a grid column programmatically (instead of clicking on the filter drop-down menu in the column header). When the function is first launched, the grid storage is rebooted without a filter. When I run the function a second time (and every time after that), it works completely fine, the store is reloaded with filters. Here is the gist of my function:

// a filter object for testing aFilter = {type: 'date', field: 'a_date_field', comparison: 'gt', value: '2012-03-08 00:00:00'} var grid = Ext.create('Ext.grid.Panel', { store: store, features: [{ ftype: 'filters', }], columns[{ header: 'ID', dataIndex: 'id', itemId: 'id', width: 40, }, { xtype: 'datecolumn', header: 'Date', dataIndex: 'a_date_field', itemId: 'a_date_field', width: 75, format:'jM-Y', filterable: true }], listeners: { 'afterrender': function() { // Need to create the filters as soon as the grid renders // rather than waiting for the user to click on the header grid.filters.createFilters(); } }, bbar: [{ text: 'Do a filter', handler: function() { // get the filter that is attached to the grid var gridFilter = grid.filters.getFilter(aFilter.field); // have to do this to create a menu for this filter gridFilter.init({dataIndex: aFilter.field, type: aFilter.type, active: true}); // if this column is a date filter column if (gridFilter.type == 'date') { var dateValue = Ext.Date.parse(aFilter.value, 'Ymd H:i:s'); if (filter.comparison == 'gt') { gridFilter.setValue({after: dateValue}); } else { gridFilter.setValue({before: dateValue}); } } } } }); 

I also found that this function works for the first time if I click on any menu of the grid header before starting the function.

I tried to find out what changes were made to the grid that make the filter work after the first attempt unsuccessful or that clicking on any grid header makes it work. But nothing that I add seems to fix it, so it will work for the first time. Has anyone implemented this successfully?

+6
source share
7 answers

I have a workaround:

 bbar: [{ text: 'Do a filter', handler: function() { var grid = this.up('grid'); var dateValue = Ext.Date.parse(aFilter.value, 'Ymd H:i:s'); var value = aFilter.comparison == 'gt' ? {after: dateValue} : {before: dateValue}; var gridFilter = grid.filters.getFilter(aFilter.field); if (!gridFilter) { gridFilter = grid.filters.addFilter({ active: true, type: aFilter.type, dataIndex: aFilter.dataIndex, }); gridFilter.menu.show(); gridFilter.setValue(value); gridFilter.menu.hide(); } else { gridFilter.setActive(true); } Ext.Function.defer(function(){ gridFilter = grid.filters.getFilter(aFilter.field); gridFilter.setValue(value); }, 10); } }] 

As you can see, I actually apply the filter 2 times.

+9
source

As an update, I expanded this feature and modified it to work with ExtJS 4.1.1

Here is an example of a function that allows you to dynamically set grid filters (without having to click on the menu items). After that, the filtered elements will be visible to the user in the menu of the column headers of the grid, as if he clicked on them and set them manually.

The grid argument is the FiltersFeature grid that you want to filter. Another argument is an array of filter objects (I will show an example below), the function simply applies all the transferred filtering objects to the grid.

 doGridFilter: function(grid, filters) { // for each filter object in the array Ext.each(filters, function(filter) { var gridFilter = grid.filters.getFilter(filter.field); gridFilter.setActive(true); switch(filter.data.type) { case 'date': var dateValue = Ext.Date.parse(filter.data.value, 'm/d/Y'), value; switch (filter.data.comparison) { case 'gt' : value = {after: dateValue}; break; case 'lt' : value = {before: dateValue}; break; case 'eq' : value = {on: dateValue}; break; } gridFilter = log.filters.getFilter(filter.field); gridFilter.setValue(value); gridFilter.setActive(true); break; case 'numeric': var value; switch (filter.data.comparison) { case 'gt' : value = {gt: filter.data.value}; break; case 'lt' : value = {lt: filter.data.value}; break; case 'eq' : value = {eq: filter.data.value}; break; } gridFilter = log.filters.getFilter(filter.field); gridFilter.setValue(value); gridFilter.setActive(true); break; case 'list': gridFilter = log.filters.getFilter(filter.field); gridFilter.menu.setSelected(gridFilter.menu.selected, false); gridFilter.menu.setSelected(filter.data.value.split(','), true); break; default : gridFilter = log.filters.getFilter(filter.field); gridFilter.setValue(filter.data.value); break; } }); } 

Here is an example of an array of filter objects.

 // an example of a "filters" argument [{ field: 'some_list_column_data_index', data: { type: 'list', value: 'item1,item2,item3,item4,item5,item6,item7' } }, { field: 'some_date_column_data_index', data: { type: 'date', comparison: 'gt', value: '07/07/2007' } }] 

Caution, you need to "create" filters manually before using this function. Typically, FiltersFeature mesh filters are “created” the first time the user FiltersFeature one of them, which might not happen if the user just wants to apply one of these predefined filters.

This can be easily handled by turning on this listener after listening to the grid.

 listeners: { // must create the filters after grid is rendered afterrender: function(grid) { grid.filters.createFilters(); } } 
+6
source

Just add

 filter: true 

to describe the grid columns as follows:

 me.columns = [ {header:"Name", dataIndex:"name", editor:"textfield", filter: true}, ]; 

if you want the filter to work after the first attempt, create the first instance.

+3
source

Here's what it might be worth a look. The filter plugin seems to listen for the menucreate event to initialize the filters. I wonder if the menu creation event is delayed until it is needed, and therefore the filters are not initialized?

 /** * @private Handle creation of the grid header menu. Initializes the filters and listens * for the menu being shown. */ onMenuCreate: function(headerCt, menu) { var me = this; me.createFilters(); //<------ menu.on('beforeshow', me.onMenuBeforeShow, me); }, 
+1
source

Do you want to apply a mesh filter or maybe the store.filter () function is better for you? In this case, just filter the storage, and the grid will display the filtered records.

0
source

I discovered another way to implement this. It appears that the grid functions are only tied to the grid after rendering the grid. This means that any filter setting does not take effect until the grid is displayed. The store’s bootstrap is apparently triggered before the grid is rendered.

I solved the problem by creating my own store with a memory proxy that does not contain data.

 me.store = Ext.create('Ext.data.Store', { model: 'SummaryData', data: [], proxy: { type: 'memory', reader: 'array' }, remoteSort: true, remoteFilter: true }); 

Then configure the afterrender handler on the grid to navigate the correct proxy and start loading the repository.

 afterrender: function () { var me = this; me.store.setProxy({ type: 'ajax', url : '/print_unallocated/change_site__data', reader: { type: 'json', root: 'rows' }, listeners: { exception: function (proxy, response) { Max.reportException(response); } } }); me.filters.createFilters(); me.store.load(); }, 
0
source

In the source code you can see a comment related to this.

 // Call getMenu() to ensure the menu is created, and so, also are the filters. We cannot call // createFilters() withouth having a menu because it will cause in a recursion to applyState() // that ends up to clear all the filter values. This is likely to happen when we reorder a column // and then add a new filter before the menu is recreated. me.view.headerCt.getMenu(); 

You can check if a menu has been created before applying the filter. If it is not, do it yourself.

 if(!grid.getView().headerCt.menu){ grid.getView().headerCt.getMenu(); } 
0
source

Source: https://habr.com/ru/post/910317/


All Articles