Skip to content

Commit

Permalink
Add debounce search to table
Browse files Browse the repository at this point in the history
  • Loading branch information
jtommy committed Aug 24, 2020
1 parent cc64eac commit 30a3c0a
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 18 deletions.
3 changes: 3 additions & 0 deletions packages/docs/components/Table.md
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,8 @@ title: Table
<section>
<o-table :data="data" :columns="columns"> </o-table>
<hr />
<p>You can debounce search filter to avoid multiple filtering when typing.</p>
<o-table :data="data" :columns="columns" :debounce-search="1000"> </o-table>
<p>You can also customize the search input using a scoped slot.</p>
<o-table :data="data">
<template v-for="column in columns">
Expand Down Expand Up @@ -910,6 +912,7 @@ title: Table
| height | Table fixed height | number\|string | - | |
| filtersEvent | Add a native event to filter | string | - | '' |
| cardLayout | Force to show table with cards layout | boolean | - | |
| debounceSearch | Filtering debounce time (in milliseconds) | number | - | |
| showHeader | Show header | boolean | - | Config -> <code> 'table.showHeader': true</code> |
| rootClass | | string | - | |
| wrapperClass | | string | - | |
Expand Down
125 changes: 125 additions & 0 deletions packages/oruga/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/oruga/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"rollup-copy-plugin": "0.1.0",
"rollup-plugin-terser": "6.1.0",
"rollup-plugin-vue": "5.1.9",
"sinon": "9.0.3",
"typescript": "3.8.3",
"vue": "2.6.11",
"vue-class-component": "7.2.3",
Expand Down
17 changes: 17 additions & 0 deletions packages/oruga/src/components/table/Table.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Vue from 'vue'
import { shallowMount } from '@vue/test-utils'
import { useFakeTimers } from 'sinon'
import OInput from '@components/input/Input'
import OTable from '@components/table/Table'
import { setVueInstance } from '../../utils/config'
Expand Down Expand Up @@ -140,5 +141,21 @@ describe('OTable', () => {
bodyRows = wrapper.findAll('tbody tr')
expect(bodyRows).toHaveLength(3) // Jesse, John and Justin
})

it('debounce search filtering when debounce-search is defined', () => {
let clock = useFakeTimers()
wrapper.setProps({
debounceSearch: 1000
})
for (let i = 0; i < 10; i++) {
searchInput.vm.$emit('input', 'J'.repeat(10 - i))
clock.tick(500)
bodyRows = wrapper.findAll('tbody tr')
expect(bodyRows).toHaveLength(5) // No filtering yet
}
clock.tick(1000)
bodyRows = wrapper.findAll('tbody tr')
expect(bodyRows).toHaveLength(2) // Filtering after debounce
})
})
})
49 changes: 32 additions & 17 deletions packages/oruga/src/components/table/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@

<script>
import BaseComponentMixin from '../../utils/BaseComponentMixin'
import { getValueByPath, indexOf, multiColumnSort, toCssDimension } from '../../utils/helpers'
import { getValueByPath, indexOf, multiColumnSort, toCssDimension, debounce } from '../../utils/helpers'
import config from '../../utils/config'
import { VueInstance } from '../../utils/config'
Expand Down Expand Up @@ -557,6 +557,8 @@ export default {
},
/** Force to show table with cards layout */
cardLayout: Boolean,
/** Filtering debounce time (in milliseconds) */
debounceSearch: Number,
/** Show header */
showHeader: {
type: Boolean,
Expand Down Expand Up @@ -885,24 +887,19 @@ export default {
this.newCheckedRows = [...rows]
},
debounceSearch: {
handler(value) {
this.debouncedHandleFiltersChange = debounce(this, this.handleFiltersChange, value)
},
immediate: true
},
filters: {
handler(value) {
if (this.backendFiltering) {
this.$emit('filters-change', value)
if (this.debounceSearch) {
this.debouncedHandleFiltersChange(value)
} else {
this.newData = this.data.filter(
(row) => this.isRowFiltered(row))
if (!this.backendPagination) {
this.newDataTotal = this.newData.length
}
if (!this.backendSorting) {
if (this.sortMultiple &&
this.sortMultipleDataLocal && this.sortMultipleDataLocal.length > 0) {
this.doSortMultiColumn()
} else if (Object.keys(this.currentSortColumn).length > 0) {
this.doSortSingleColumn(this.currentSortColumn)
}
}
this.handleFiltersChange(value)
}
},
deep: true
Expand Down Expand Up @@ -972,10 +969,28 @@ export default {
{ [this.computedClass('table', 'detailedIconExpandedClass', 'o-table-detail-icon-expanded')]: this.isVisibleDetailRow(row) }
]
},
onFiltersEvent(event) {
this.$emit(`filters-event-${this.filtersEvent}`, { event, filters: this.filters })
},
handleFiltersChange(value) {
if (this.backendFiltering) {
this.$emit('filters-change', value)
} else {
this.newData = this.data.filter(
(row) => this.isRowFiltered(row))
if (!this.backendPagination) {
this.newDataTotal = this.newData.length
}
if (!this.backendSorting) {
if (this.sortMultiple &&
this.sortMultipleDataLocal && this.sortMultipleDataLocal.length > 0) {
this.doSortMultiColumn()
} else if (Object.keys(this.currentSortColumn).length > 0) {
this.doSortSingleColumn(this.currentSortColumn)
}
}
}
},
findIndexOfSortData(column) {
const sortObj = this.sortMultipleDataComputed.filter((i) => i.field === column.field)[0]
return this.sortMultipleDataComputed.indexOf(sortObj) + 1
Expand Down
6 changes: 6 additions & 0 deletions packages/oruga/src/components/table/examples/Table.md
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,12 @@
:columns="columns">
</o-table>
<hr />
<p>You can debounce search filter to avoid multiple filtering when typing.</p>
<o-table
:data="data"
:columns="columns"
:debounce-search="1000">
</o-table>
<p>You can also customize the search input using a scoped slot.</p>
<o-table
:data="data">
Expand Down
56 changes: 55 additions & 1 deletion packages/oruga/src/utils/helpers.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { getValueByPath, indexOf, merge, escapeRegExpChars, removeElement } from './helpers'
import { useFakeTimers } from 'sinon'
import {
getValueByPath, indexOf, merge,
escapeRegExpChars, removeElement, debounce
} from './helpers'

describe('helpers', () => {
describe('getValueByPath', () => {
Expand Down Expand Up @@ -143,4 +147,54 @@ describe('helpers', () => {
expect(elm.parentNode.removeChild).toHaveBeenCalled()
})
})

let clock
let func
beforeEach(() => {
clock = useFakeTimers()
func = jest.fn()
})

afterEach(() => {
clock.restore()
})

describe('debounce', () => {
it('is not called immediately', () => {
const debouncedFunc = debounce(func, 1000)
debouncedFunc()
expect(func).toHaveBeenCalledTimes(0)
})

it('is not called upon several rapid calls', () => {
const debouncedFunc = debounce(func, 1000)
for (let i = 0; i < 10; i++) {
clock.tick(500)
debouncedFunc()
}
expect(func).toHaveBeenCalledTimes(0)
})

it('is called after debounce time', () => {
const debouncedFunc = debounce(func, 1000)
debouncedFunc()
clock.tick(1000)
expect(func).toHaveBeenCalledTimes(1)
})

it('is called immediately if immediate is true', () => {
const debouncedFunc = debounce(func, 1000, true)
debouncedFunc()
expect(func).toHaveBeenCalledTimes(1)
})

it('is called once upon several rapid calls if immediate is true', () => {
const debouncedFunc = debounce(func, 1000, true)
for (let i = 0; i < 10; i++) {
clock.tick(500)
debouncedFunc()
}
expect(func).toHaveBeenCalledTimes(1)
})
})
})

0 comments on commit 30a3c0a

Please sign in to comment.