最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Toggle floating filter in Ag-Grid? - Stack Overflow

programmeradmin7浏览0评论

I am trying to have the display of the floating filter be determined by a switch or button click. Seems simple enough. I should just be able to toggle between true and false, supply that value to the floating filter in the grid options, and refresh the header right? Unfortunately, the grid always seems to be one step behind. When I click the first time, nothing happens. When I toggle the switch back to false is when the floating filter es up. The floating filter will then continue to appear (when the switch is false) and disappear (when the switch is true). To make things even weirder, if I toggle the floating filter switch a few times and then try toggling the rowGroupPanelShow (which I am also trying to have toggleable), it will trigger the floating filter to switch to whatever value it was not previously. But only once.

I have tried a few variations on this. I've tried switches and buttons. I've tried watchers and writing my own functions to toggle true and false. I've tried calling this.gridApi.refreshHeader() within the same function as the toggle and calling it from it's own function. I've tried calling this.columnApi.resetColumnState() (works for resetting grouping). Everything console logs correctly but the grid always seems to be one step behind.

Here's a link to a plunker that I took from ag-grid's website and modified to demonstrate the behavior:

Here is the switch and the grid:

<v-layout row wrap justify-center>
  <v-flex xs6 sm2 md2>
    <v-switch
      class="switch"
      color="blue"
      id="filterSwitch"
      label="Floating Filter"
      v-model="filterSwitch"
    ></v-switch>
  </v-flex>
  <v-flex xs6 sm2 md2>
    <v-switch
      class="switch"
      color="blue"
      id="groupSwitch"
      label="Row Grouping Panel"
      v-model="groupSwitch"
    ></v-switch>
  </v-flex>
</v-layout>
<div class="buys">
  <ag-grid-vue
  id="personTableAgGridTest"
  style="width: 100%; height: 65vh;"
  class="ag-theme-balham"
  :columnDefs="columnDefs"
  :rowData="rowData"
  :cacheBlockSize="cacheBlockSize"
  :rowModelType="rowModelType"
  :enableColResize="true"
  :enableFilter="true"
  :enableSorting="true"
  :rowSelection="rowSelection"
  :animateRows="true"
  :floatingFilter="floatingFilter"
  :maxConcurrentDatasourceRequests="maxConcurrentDatasourceRequests"
  :defaultColDef="defaultColDef"
  :columnTypes="columnTypes"
  :sideBar="sideBar"
  :rowGroupPanelShow="rowGroupPanelShow"
  :gridReady="onGridReady"
  >

  </ag-grid-vue>

Here is the relevant bound data

export default {
  data() {
    return {
      columnDefs: null,
      rowData: null,
      cacheBlockSize: 250,
      rowSelection: 'multiple',
      maxBlocksInCache: 5,
      gridApi: null,
      columnApi: null,
      rowGroupPanelShow: 'always',
      floatingFilter: false,
      filterSwitch: false,
      groupSwitch: false,
      rowModelType: 'serverSide',
      maxConcurrentDatasourceRequests: 1,

Here are the functions/watchers

    resetColumns () {
      this.columnApi.resetColumnState()
    },
    refreshHeader2 () {
      console.log('in refresh header', this.floatingFilter)
      this.gridApi.refreshHeader()
      // this.resetColumns()
    }
 },
  watch: {
    filterSwitch (val) {
      console.log('val', val, this.floatingFilter)
      this.floatingFilter = !this.floatingFilter
      this.refreshHeader2()
    },

Expected: Whether or not the floating filter is shown should be toggled by a switch. Passing the value of the switch to the grid and then refreshing the header should acplish this.

Actual: Grid seems to be one step behind (shows floating filter when switch is false).

I am trying to have the display of the floating filter be determined by a switch or button click. Seems simple enough. I should just be able to toggle between true and false, supply that value to the floating filter in the grid options, and refresh the header right? Unfortunately, the grid always seems to be one step behind. When I click the first time, nothing happens. When I toggle the switch back to false is when the floating filter es up. The floating filter will then continue to appear (when the switch is false) and disappear (when the switch is true). To make things even weirder, if I toggle the floating filter switch a few times and then try toggling the rowGroupPanelShow (which I am also trying to have toggleable), it will trigger the floating filter to switch to whatever value it was not previously. But only once.

I have tried a few variations on this. I've tried switches and buttons. I've tried watchers and writing my own functions to toggle true and false. I've tried calling this.gridApi.refreshHeader() within the same function as the toggle and calling it from it's own function. I've tried calling this.columnApi.resetColumnState() (works for resetting grouping). Everything console logs correctly but the grid always seems to be one step behind.

Here's a link to a plunker that I took from ag-grid's website and modified to demonstrate the behavior: https://plnkr.co/edit/Me51NOVOCbmvFxx95WpP?p=preview

Here is the switch and the grid:

<v-layout row wrap justify-center>
  <v-flex xs6 sm2 md2>
    <v-switch
      class="switch"
      color="blue"
      id="filterSwitch"
      label="Floating Filter"
      v-model="filterSwitch"
    ></v-switch>
  </v-flex>
  <v-flex xs6 sm2 md2>
    <v-switch
      class="switch"
      color="blue"
      id="groupSwitch"
      label="Row Grouping Panel"
      v-model="groupSwitch"
    ></v-switch>
  </v-flex>
</v-layout>
<div class="buys">
  <ag-grid-vue
  id="personTableAgGridTest"
  style="width: 100%; height: 65vh;"
  class="ag-theme-balham"
  :columnDefs="columnDefs"
  :rowData="rowData"
  :cacheBlockSize="cacheBlockSize"
  :rowModelType="rowModelType"
  :enableColResize="true"
  :enableFilter="true"
  :enableSorting="true"
  :rowSelection="rowSelection"
  :animateRows="true"
  :floatingFilter="floatingFilter"
  :maxConcurrentDatasourceRequests="maxConcurrentDatasourceRequests"
  :defaultColDef="defaultColDef"
  :columnTypes="columnTypes"
  :sideBar="sideBar"
  :rowGroupPanelShow="rowGroupPanelShow"
  :gridReady="onGridReady"
  >

  </ag-grid-vue>

Here is the relevant bound data

export default {
  data() {
    return {
      columnDefs: null,
      rowData: null,
      cacheBlockSize: 250,
      rowSelection: 'multiple',
      maxBlocksInCache: 5,
      gridApi: null,
      columnApi: null,
      rowGroupPanelShow: 'always',
      floatingFilter: false,
      filterSwitch: false,
      groupSwitch: false,
      rowModelType: 'serverSide',
      maxConcurrentDatasourceRequests: 1,

Here are the functions/watchers

    resetColumns () {
      this.columnApi.resetColumnState()
    },
    refreshHeader2 () {
      console.log('in refresh header', this.floatingFilter)
      this.gridApi.refreshHeader()
      // this.resetColumns()
    }
 },
  watch: {
    filterSwitch (val) {
      console.log('val', val, this.floatingFilter)
      this.floatingFilter = !this.floatingFilter
      this.refreshHeader2()
    },

Expected: Whether or not the floating filter is shown should be toggled by a switch. Passing the value of the switch to the grid and then refreshing the header should acplish this.

Actual: Grid seems to be one step behind (shows floating filter when switch is false).

Share Improve this question edited Jan 30, 2019 at 22:00 Reese Westerhoff asked Jan 30, 2019 at 16:12 Reese WesterhoffReese Westerhoff 1092 silver badges8 bronze badges 5
  • Your question would be easier to answer with a demo showing the problem. You can try starting from this: plnkr.co/edit/RQcNJT2sKcv65JzNMmeU?p=preview. Or any of the other examples from the documentation. – thirtydot Commented Jan 30, 2019 at 20:55
  • Thanks for the reply @thirtydot. I just added a link to a plunker that I grabbed from ag-grid's website and modified to show what is happening. plnkr.co/edit/Me51NOVOCbmvFxx95WpP?p=preview – Reese Westerhoff Commented Jan 30, 2019 at 22:02
  • I don't know Vue.js very well, but I have an inkling of what could be happening. This seems to help: plnkr.co/edit/9NAfPeEu8GgJw7okqz77?p=preview. I don't have a clue what's going on with "Reset Columns" and didn't investigate. – thirtydot Commented Jan 30, 2019 at 23:06
  • Hey! I got distracted cause your solution worked and I pletely forgot to e back here and say thank you!! It's working great. Strange that you would have to add a set timeout of 0ms for it to work, but it does. Thank you @thirtydot! – Reese Westerhoff Commented Feb 5, 2019 at 14:47
  • You're wele. I've written an answer with a few more details so you have something to accept. – thirtydot Commented Feb 5, 2019 at 17:04
Add a ment  | 

3 Answers 3

Reset to default 6

In my ment I suggested fixing it with setTimeout(..., 0):

https://plnkr.co/edit/9NAfPeEu8GgJw7okqz77?p=preview

watch: {
    filterSwitch () {
        // logs correctly with value of filterSwitch
        console.log('filterSwitch', this.filterSwitch)
        setTimeout(() => {
            // refresh header after value of floating filter has changed
            this.gridApi.refreshHeader()
        }, 0);
    }
},

Here's some general information: Why is setTimeout(fn, 0) sometimes useful?

In React (which I know) I would use the setState callback:

this.setState({
    filterSwitch: !filterSwitch,
}, () => {
    this.gridApi.refreshHeader();
});

I don't know if there's a Vue.js equivalent, but setTimeout(..., 0) acplishes a similar thing.

For Angular: Component code behind file

 gridApi: any = null;
  floatingFilter = false;
  onGridReady(grid: any) {
    this.gridApi = grid.api;
  }
  toggleFloating(){
        this.floatingFilter = !this.floatingFilter;
         const columnDefs = this.gridApi.getColumnDefs();
         columnDefs.forEach((colDef:any, index:number)=> {
            colDef.floatingFilter = this.floatingFilter;
         });
         this.gridApi.setColumnDefs(columnDefs);
  }

Html:

 <ag-grid-angular style="width: 100%; height: 300px;" class="ag-theme-alpine" [rowData]="rowData" [gridOptions]="gridOptions"
        (gridReady)="onGridReady($event)">
    </ag-grid-angular>

This may be a standard situation in React, where we need to use the useEffect hook, observing the change in the flag and then reacting to it.

In the button or switch UI, the boolean flag isFilterOn is being toggled. Then the filter is being toggled with the below code. Note that .

import { useEffect, useState } from 'react'

...

// initial values for defaultColDef
// if filter is true, then we can skip setting it later
// defaultColDef: { filter: false, sortable: true, floatingFilter: false },

This is the flag which is toggled with a button click / etc

const [isFilterOn, setIsFilterOn] = useState(false)

This is where we can hide or show the filter depending on the flag.

  useEffect(() => {
    console.log('isFilterOn ' + isTableView)
    if (!gridOptions) return

    let colDefs = gridOptions.api.getColumnDefs()
    colDefs.forEach((colDef) => {
      colDef.floatingFilter = isFilterOn
      colDef.filter = isFilterOn
    })
    let columnDefs = colDefs
    gridOptions.api.setColumnDefs(columnDefs)
    gridOptions.api.refreshHeader()
  }, [isFilterOn])

Ref: plnkr where its implemented - shown in the last response (skip earlier responses) in this issue

useEffect hook in more detail.

发布评论

评论列表(0)

  1. 暂无评论