bootstrap-vue: b-table: Filter Debounce does not work with computed properties or data attributes in the custom filter function

Describe the bug

filter-debounce no longer works if the custom filter-function attempts to access a data or computed property.

Steps to reproduce the bug

This fiddle will illustrate the issue: https://jsfiddle.net/0jd54wpn/1/

Notice you can try it by accessing the computed property, the data property, or both. Just comment out and see the results. Comment both if statements in filterFunction to see debounce working as expected.

Expected behavior

I expect the debouncer to work no matter what you need or try to access from within the custom filter function.

Versions

Libraries:

  • BootstrapVue: 2.0.2
  • Bootstrap: 4.3.1
  • Vue: 2.6.10

Environment:

  • Device: Windows
  • OS: 10 Pro
  • Browser: Chrome
  • Version: 77.0.3865.90

Demo link

JSFiddle

Additional context

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 27 (15 by maintainers)

Most upvoted comments

BootstrapVue v2.1.0 has been released, which has added debouncing support to b-form-input (use this instead of the filter-debounce feature of <b-table>)

@WillGoldstein Bootstrap v2.0.4 has been released with further performance improvements for b-table/b-table-lite

BootstrapVue v2.0.3 has been released, which includes some performance enhancements for tables.

@WillGoldstein As a workaround, you could implement your own debounce routine on an input that, once debounced, passes the filter criteria to b-table:

Using a watcher:

<template>
  <div>
    <b-form-input v-model="rawInput" type="search"></b-form-input>
    <b-table :items="items" :fields="fields" :filter="criteria"></b-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      rawInput: '',
      criteria: '',
      // ...
    }
  },
  created() {
    // Use a non-reactive property to prevent
    // unnecessary re-renders of your component
    this.$_timeout = null
  },
  beforeDestroy() {
    // Ensure that any pending timeout is cleared on destroy
    clearTimeout(this.$_timeout)
  },
  watch: {
    rawInput(newVal, oldVal) {
      clearTimeout(this.$_timeout)
      this.$_timeout = setTimeout(() => {
        this.criteria = newVal
      }, 150) // set this value to your preferred debounce timeout
    }
  }
}
</script>

Or using event on the input

<template>
  <div>
    <!-- update is the event that updates the v-model on b-form-input -->
    <b-form-input @update="handleFilter" type="search"></b-form-input>
    <b-table :items="items" :fields="fields" :filter="criteria"></b-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      criteria: '',
      // ...
    }
  },
  created() {
    // Use a non-reactive property to prevent
    // unnecessary re-renders of your component
    this.$_timeout = null
  },
  beforeDestroy() {
    // Ensure that any pending timeout is cleared on destroy
    clearTimeout(this.$_timeout)
  },
  methods: {
    handleFilter(val) {
      clearTimeout(this.$_timeout)
      this.$_timeout = setTimeout(() => {
        this.criteria = val
      }, 150) // set this value to your preferred debounce timeout
    }
  }
}
</script>

@WillGoldstein After a bit of digging, we’ve discovered one thing.

Whenever a prop changes on a component, even if it isn’t directly (or indirectly) used during render, causes the component to re-render (since Vue doesn’t track what causes a render function to update - any data or prop change will cause a render - unlike computed props which track what changes).

Therefor, whenever the filter prop changes, even when debounced, will cause the table component to re-render (although the filtering wont be applied until after the debounce).

What we will probably do (in release v2.1.0) is:

  • add a debounce feature to <b-form-input> (and by nature <b-form-textarea>)
  • add new prop lazy to <b-form-input>(and by nature <b-form-textarea>), which updates the v-model on change/blur (PR #4169)
  • deprecate the filter debounce feature of <b-table> in favour of the input debounce

This will decouple the filter criteria value change, optimizing the render updates

We’ll close the issue once v2.1.0 is released.

PR #4314 adds built-in debouncing support to b-form-input and b-form-textarea.

When enabled, user input (keypresses) will be debounced by the specified timeout, updating the v-model (via the update event). If a change event happens before the debounce timeout expires (i.e. on input blur), the v-model will update immediately.

Will be available once v2.1.0 is released

v2.0.3 will have some performance improvements for tables (mainly for faster render time and reduced runtime memory footprint), which may help a bit.