From 929181be6185c537cba58971799cbfeab39930ef Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Mon, 5 Mar 2018 09:17:49 -0800 Subject: [PATCH 1/2] Add onChange callback to search config object. --- .../in_memory/in_memory_search_callback.js | 137 ++++++++++++++++++ .../in_memory_search_callback_section.js | 35 +++++ src-docs/src/views/tables/in_memory/index.js | 1 + src-docs/src/views/tables/tables_example.js | 4 +- src/components/basic_table/in_memory_table.js | 11 +- 5 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 src-docs/src/views/tables/in_memory/in_memory_search_callback.js create mode 100644 src-docs/src/views/tables/in_memory/in_memory_search_callback_section.js diff --git a/src-docs/src/views/tables/in_memory/in_memory_search_callback.js b/src-docs/src/views/tables/in_memory/in_memory_search_callback.js new file mode 100644 index 00000000000..a0bc358ef23 --- /dev/null +++ b/src-docs/src/views/tables/in_memory/in_memory_search_callback.js @@ -0,0 +1,137 @@ +import React, { Fragment } from 'react'; +import { formatDate } from '../../../../../src/services/format'; +import { createDataStore } from '../data_store'; +import { + EuiInMemoryTable, + EuiLink, + EuiHealth, + EuiSpacer, + EuiSwitch, + EuiFlexGroup, + EuiFlexItem +} from '../../../../../src/components'; + +/* +Example user object: + +{ + id: '1', + firstName: 'john', + lastName: 'doe', + github: 'johndoe', + dateOfBirth: Date.now(), + nationality: 'NL', + online: true +} + +Example country object: + +{ + code: 'NL', + name: 'Netherlands', + flag: '🇳🇱' +} +*/ + +let debounceTimeoutId; +let requestTimeoutId; +const store = createDataStore(); + +export class Table extends React.Component { + + constructor(props) { + super(props); + + this.state = { + items: store.users, + isLoading: false, + }; + } + + onQueryChange = query => { + clearTimeout(debounceTimeoutId); + clearTimeout(requestTimeoutId); + + debounceTimeoutId = setTimeout(() => { + this.setState({ + isLoading: true, + }); + + requestTimeoutId = setTimeout(() => { + const items = store.users.filter(user => { + const normalizedName = `${user.firstName} ${user.lastName}`.toLowerCase(); + const normalizedQuery = query.text.toLowerCase(); + return normalizedName.indexOf(normalizedQuery) !== -1; + }); + + this.setState({ + isLoading: false, + items, + }) + }, 1000); + }, 300); + }; + + render() { + const search = { + onChange: this.onQueryChange, + box: { + incremental: true, + }, + }; + + return ( + ( + {username} + ) + }, + { + field: 'dateOfBirth', + name: 'Date of Birth', + dataType: 'date', + render: (date) => formatDate(date, 'dobLong'), + sortable: true + }, + { + field: 'nationality', + name: 'Nationality', + render: (countryCode) => { + const country = store.getCountry(countryCode); + return `${country.flag} ${country.name}`; + } + }, + { + field: 'online', + name: 'Online', + dataType: 'boolean', + render: (online) => { + const color = online ? 'success' : 'danger'; + const label = online ? 'Online' : 'Offline'; + return {label}; + }, + sortable: true + } + ]} + search={search} + pagination={true} + sorting={true} + /> + ); + } +} diff --git a/src-docs/src/views/tables/in_memory/in_memory_search_callback_section.js b/src-docs/src/views/tables/in_memory/in_memory_search_callback_section.js new file mode 100644 index 00000000000..d7e30829617 --- /dev/null +++ b/src-docs/src/views/tables/in_memory/in_memory_search_callback_section.js @@ -0,0 +1,35 @@ +import React from 'react'; +import { + EuiCode +} from '../../../../../src/components'; +import { GuideSectionTypes } from '../../../components'; +import { renderToHtml } from '../../../services'; + +import { Table } from './in_memory_search_callback'; +import { propsInfo } from './props_info'; + +const source = require('!!raw-loader!./in_memory_search_callback'); +const html = renderToHtml(Table); + +export const searchCallbackSection = { + title: 'In-Memory Table - With Search Callback', + source: [ + { + type: GuideSectionTypes.JS, + code: source, + }, { + type: GuideSectionTypes.HTML, + code: html, + } + ], + text: ( +
+

+ The example shows how to configure EuiInMemoryTable to display a search bar + and intercept the search value when it changes so you can perform your own search logic. +

+
+ ), + props: propsInfo, + demo: +}; diff --git a/src-docs/src/views/tables/in_memory/index.js b/src-docs/src/views/tables/in_memory/index.js index 316d8145c00..d9ed00d669f 100644 --- a/src-docs/src/views/tables/in_memory/index.js +++ b/src-docs/src/views/tables/in_memory/index.js @@ -1,3 +1,4 @@ export { section } from './in_memory_section'; export { selectionSection } from './in_memory_selection_section'; export { searchSection } from './in_memory_search_section'; +export { searchCallbackSection } from './in_memory_search_callback_section'; diff --git a/src-docs/src/views/tables/tables_example.js b/src-docs/src/views/tables/tables_example.js index 00b372b0367..d6e36f67485 100644 --- a/src-docs/src/views/tables/tables_example.js +++ b/src-docs/src/views/tables/tables_example.js @@ -16,7 +16,8 @@ import { section as actionsSection } from './actions'; import { section as inMemorySection, selectionSection as inMemorySelectionSection, - searchSection as inMemorySearchSection + searchSection as inMemorySearchSection, + searchCallbackSection as inMemorySearchCallbackSection, } from './in_memory'; import { section as customSection } from './custom'; @@ -53,6 +54,7 @@ export const TableExample = { inMemorySection, inMemorySelectionSection, inMemorySearchSection, + inMemorySearchCallbackSection, customSection, ], }; diff --git a/src/components/basic_table/in_memory_table.js b/src/components/basic_table/in_memory_table.js index c8f840dad1c..ad4ed30d882 100644 --- a/src/components/basic_table/in_memory_table.js +++ b/src/components/basic_table/in_memory_table.js @@ -29,6 +29,7 @@ const InMemoryTablePropTypes = { defaultQuery: QueryType, box: PropTypes.shape(SearchBoxConfigPropTypes), filters: SearchFiltersFiltersType, + onChange: PropTypes.func, })]), pagination: PropTypes.oneOfType([ PropTypes.bool, @@ -112,6 +113,10 @@ export class EuiInMemoryTable extends React.Component { } onQueryChange(query) { + if (this.props.search.onChange) { + return this.props.search.onChange(query); + } + this.setState(prevState => ({ query, data: this.computeData(this.props.items, prevState.criteria, query) @@ -162,7 +167,11 @@ export class EuiInMemoryTable extends React.Component { resolveSearchBar() { const { search } = this.props; if (search) { - const searchBarProps = isBoolean(search) ? {} : search; + const { + onChange, // eslint-disable-line no-unused-vars + ...searchBarProps + } = isBoolean(search) ? {} : search; + return ( Date: Wed, 7 Mar 2018 13:01:20 -0800 Subject: [PATCH 2/2] Let consumer allow in-memory searching to proceed normally. --- src-docs/src/views/tables/in_memory/props_info.js | 5 +++++ src/components/basic_table/in_memory_table.js | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src-docs/src/views/tables/in_memory/props_info.js b/src-docs/src/views/tables/in_memory/props_info.js index e059e78b702..eaf6deb6223 100644 --- a/src-docs/src/views/tables/in_memory/props_info.js +++ b/src-docs/src/views/tables/in_memory/props_info.js @@ -80,6 +80,11 @@ export const propsInfo = { description: 'Configures the search filters of the search bar ', required: false, type: { name: '#SearchFilters' } + }, + onChange: { + description: 'Callback for when the search bar value changes. By default this will prevent in-memory searching. Return `true` to allow in-memory searching.', + required: false, + type: { name: 'function' } } } } diff --git a/src/components/basic_table/in_memory_table.js b/src/components/basic_table/in_memory_table.js index ad4ed30d882..d6f48095370 100644 --- a/src/components/basic_table/in_memory_table.js +++ b/src/components/basic_table/in_memory_table.js @@ -114,7 +114,9 @@ export class EuiInMemoryTable extends React.Component { onQueryChange(query) { if (this.props.search.onChange) { - return this.props.search.onChange(query); + const shouldQueryInMemory = this.props.search.onChange(query); + + if (!shouldQueryInMemory) return; } this.setState(prevState => ({