From 2844ff7074dea9608d4a13b5aa6af441a31757e6 Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Mon, 21 May 2018 15:30:22 -0600 Subject: [PATCH 1/6] updated EuiSearchBar to React 16.3 lifecycle, refactored how its controlled-value option works --- src/components/search_bar/search_bar.js | 56 ++++++++------ src/components/search_bar/search_bar.test.js | 78 +++++++++++++++++++- 2 files changed, 111 insertions(+), 23 deletions(-) diff --git a/src/components/search_bar/search_bar.js b/src/components/search_bar/search_bar.js index 5b1e00caab2..c7a326d9d65 100644 --- a/src/components/search_bar/search_bar.js +++ b/src/components/search_bar/search_bar.js @@ -19,7 +19,7 @@ export const SearchBarPropTypes = { /** * (query: Query) => void */ - onChange: PropTypes.func.isRequired, + onChange: PropTypes.func, /** (query?: Query, queryText: string, error?: string) => void @@ -56,16 +56,12 @@ export const SearchBarPropTypes = { /** * Tools which go to the right of the search bar. */ - toolsRight: PropTypes.node, + toolsRight: PropTypes.node }; const parseQuery = (query, props) => { - const parseDate = props.box ? props.box.parseDate : undefined; const schema = props.box ? props.box.schema : undefined; - const parseOptions = { - parseDate, - schema - }; + const parseOptions = { schema }; if (!query) { return Query.parse('', parseOptions); } @@ -74,7 +70,7 @@ const parseQuery = (query, props) => { export class EuiSearchBar extends Component { - static propTypes = SearchBoxConfigPropTypes; + static propTypes = SearchBarPropTypes; static Query = Query; @@ -88,31 +84,47 @@ export class EuiSearchBar extends Component { }; } - // TODO: React 16.3 - getDerivedStateFromProps - componentWillReceiveProps(nextProps) { + static getDerivedStateFromProps(nextProps) { if (nextProps.query) { - const query = parseQuery(nextProps.query, this.props); - this.setState({ + const query = parseQuery(nextProps.query, nextProps); + return { query, queryText: query.text, error: null - }); + }; + } + return null; + } + + componentDidUpdate(oldProps, oldState) { + const { query, queryText, error } = this.state; + + const isQueryDifferent = oldState.queryText !== queryText; + + const oldError = oldState.error ? oldState.error.message : null; + const newError = error ? error.message : null; + const isErrorDifferent = oldError !== newError; + + if (isQueryDifferent || isErrorDifferent) { + if (this.props.onParse) { + this.props.onParse({ query, queryText, error }); + } + + // only fire onChange if there isn't an error + if (newError == null) { + if (this.props.onChange) { + this.props.onChange(query); + } + } } } onSearch = (queryText) => { try { const query = parseQuery(queryText, this.props); - if (this.props.onParse) { - this.props.onParse({ query, queryText }); - } this.setState({ query, queryText, error: null }); - this.props.onChange(query); } catch (e) { const error = { message: e.message }; - if (this.props.onParse) { - this.props.onParse({ queryText, error }); - } this.setState({ queryText, error }); } }; @@ -123,7 +135,9 @@ export class EuiSearchBar extends Component { queryText: query.text, error: null }); - this.props.onChange(query); + if (this.props.onChange) { + this.props.onChange(query); + } }; renderTools(tools) { diff --git a/src/components/search_bar/search_bar.test.js b/src/components/search_bar/search_bar.test.js index 8289a5c2f30..3a6bdf21bb9 100644 --- a/src/components/search_bar/search_bar.test.js +++ b/src/components/search_bar/search_bar.test.js @@ -1,7 +1,9 @@ -import React from 'react'; +/* eslint-disable react/no-multi-comp */ +import React, { Component } from 'react'; import { requiredProps } from '../../test'; -import { shallow } from 'enzyme'; +import { mount, shallow } from 'enzyme'; import { EuiSearchBar } from './search_bar'; +import { Query } from './query'; describe('SearchBar', () => { test('render - no config, no query', () => { @@ -75,4 +77,76 @@ describe('SearchBar', () => { expect(component).toMatchSnapshot(); }); + + describe('controlled input', () => { + test('calls onParse callback when a new query is passed', () => { + const onParse = jest.fn(); + + class Wrapper extends Component { + constructor(...args) { + super(...args); + this.state = { query: '' }; + } + + setQuery(query) { + this.setState({ query }); + } + + render() { + return ( + + ); + } + } + const component = mount( + + ); + + const wrapperInstance = component.instance(); + wrapperInstance.setQuery('is:active'); + + expect(onParse).toHaveBeenCalledTimes(1); + const [[{ query, queryText }]] = onParse.mock.calls; + expect(query).toBeInstanceOf(Query); + expect(queryText).toBe('is:active'); + }); + + test('does not call onParse when an unwatched prop changes', () => { + const onParse = jest.fn(); + + class Wrapper extends Component { + constructor(...args) { + super(...args); + this.state = { isFoo: false }; + } + + setIsFoo(isFoo) { + this.setState({ isFoo }); + } + + render() { + return ( + + ); + } + } + const component = mount( + + ); + + const wrapperInstance = component.instance(); + wrapperInstance.setIsFoo(true); + + expect(onParse).toHaveBeenCalledTimes(0); + }); + }); }); From 08fa9429a449ff35ad804296bc0124dfe230c353 Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Mon, 21 May 2018 15:38:18 -0600 Subject: [PATCH 2/6] revert dangling comma removal --- src/components/search_bar/search_bar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/search_bar/search_bar.js b/src/components/search_bar/search_bar.js index c7a326d9d65..539a4472a03 100644 --- a/src/components/search_bar/search_bar.js +++ b/src/components/search_bar/search_bar.js @@ -56,7 +56,7 @@ export const SearchBarPropTypes = { /** * Tools which go to the right of the search bar. */ - toolsRight: PropTypes.node + toolsRight: PropTypes.node, }; const parseQuery = (query, props) => { From 44f4c8b1bac585d9d343b05a9ff9d6bf41416edb Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Mon, 21 May 2018 15:30:22 -0600 Subject: [PATCH 3/6] updated EuiSearchBar to React 16.3 lifecycle, refactored how its controlled-value option works --- src/components/search_bar/search_bar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/search_bar/search_bar.js b/src/components/search_bar/search_bar.js index 539a4472a03..c7a326d9d65 100644 --- a/src/components/search_bar/search_bar.js +++ b/src/components/search_bar/search_bar.js @@ -56,7 +56,7 @@ export const SearchBarPropTypes = { /** * Tools which go to the right of the search bar. */ - toolsRight: PropTypes.node, + toolsRight: PropTypes.node }; const parseQuery = (query, props) => { From 8faa92f23a9770bae79d222f2d7dde4f59e5f368 Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Mon, 21 May 2018 15:50:26 -0600 Subject: [PATCH 4/6] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 523119ab7f9..3a120f19a04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## [`master`](https://github.com/elastic/eui/tree/master) +- When using `EuiSearchBar` as a controlled input, the `onParse` and `onChange` callbacks will now fire + **Bug fixes** - `EuiButton`, `EuiButtonEmpty`, and `EuiButtonIcon` now look and behave disabled when `isDisabled={true}` ([#862](https://github.com/elastic/eui/pull/862)) From 780040aca9899b6cca749d13ccdcf3f29a13d7ad Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Tue, 22 May 2018 14:48:34 -0600 Subject: [PATCH 5/6] Updated EuiSearchBar to better match the controlled component pattern, added example --- CHANGELOG.md | 4 +- .../views/search_bar/controlled_search_bar.js | 312 ++++++++++++++++++ src-docs/src/views/search_bar/props_info.js | 7 +- src-docs/src/views/search_bar/search_bar.js | 21 +- .../views/search_bar/search_bar_example.js | 24 ++ src/components/basic_table/in_memory_table.js | 2 +- src/components/search_bar/search_bar.js | 31 +- src/components/search_bar/search_bar.test.js | 85 ++--- 8 files changed, 391 insertions(+), 95 deletions(-) create mode 100644 src-docs/src/views/search_bar/controlled_search_bar.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a120f19a04..c89e3826f9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## [`master`](https://github.com/elastic/eui/tree/master) -- When using `EuiSearchBar` as a controlled input, the `onParse` and `onChange` callbacks will now fire +**Breaking changes** + +- `EuiSearchBar` no longer has an `onParse` callback, and now passes an object to `onChange` with the shape `{ query, queryText, error }` ([#863](https://github.com/elastic/eui/pull/863)) **Bug fixes** diff --git a/src-docs/src/views/search_bar/controlled_search_bar.js b/src-docs/src/views/search_bar/controlled_search_bar.js new file mode 100644 index 00000000000..de5800148f3 --- /dev/null +++ b/src-docs/src/views/search_bar/controlled_search_bar.js @@ -0,0 +1,312 @@ +import React, { Component, Fragment } from 'react'; +import { times } from 'lodash'; +import { Random } from '../../../../src/services/random'; +import { + EuiHealth, + EuiCallOut, + EuiSpacer, + EuiFlexGroup, + EuiFlexItem, + EuiSwitch, + EuiBasicTable, + EuiSearchBar, + EuiButton, +} from '../../../../src/components'; + +const random = new Random(); + +const tags = [ + { name: 'marketing', color: 'danger' }, + { name: 'finance', color: 'success' }, + { name: 'eng', color: 'success' }, + { name: 'sales', color: 'warning' }, + { name: 'ga', color: 'success' } +]; + +const types = [ + 'dashboard', + 'visualization', + 'watch', +]; + +const users = [ + 'dewey', + 'wanda', + 'carrie', + 'jmack', + 'gabic', +]; + +const items = times(10, (id) => { + return { + id, + status: random.oneOf(['open', 'closed']), + type: random.oneOf(types), + tag: random.setOf(tags.map(tag => tag.name), { min: 0, max: 3 }), + active: random.boolean(), + owner: random.oneOf(users), + followers: random.integer({ min: 0, max: 20 }), + comments: random.integer({ min: 0, max: 10 }), + stars: random.integer({ min: 0, max: 5 }) + }; +}); + +const loadTags = () => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(tags.map(tag => ({ + value: tag.name, + view: {tag.name} + }))); + }, 2000); + }); +}; + +const initialQuery = EuiSearchBar.Query.MATCH_ALL; + +export class ControlledSearchBar extends Component { + + constructor(props) { + super(props); + this.state = { + query: initialQuery, + result: items, + error: null, + incremental: false + }; + } + + onChange = ({ query, error }) => { + if (error) { + this.setState({ error }); + } else { + this.setState({ + error: null, + result: EuiSearchBar.Query.execute(query, items, { defaultFields: ['owner', 'tag', 'type'] }), + query + }); + } + }; + + toggleIncremental = () => { + this.setState(prevState => ({ incremental: !prevState.incremental })); + }; + + setQuery = query => { + this.setState({ query }); + } + + renderBookmarks() { + return ( + +

Enter a query, or select one from a bookmark

+ + + + this.setQuery('status:open owner:dewey')}>mine, open + + + this.setQuery('status:closed owner:dewey')}>mine, closed + + + +
+ ); + } + + renderSearch() { + const { incremental } = this.state; + + const filters = [ + { + type: 'field_value_toggle_group', + field: 'status', + items: [ + { + value: 'open', + name: 'Open' + }, + { + value: 'closed', + name: 'Closed' + } + ] + }, + { + type: 'is', + field: 'active', + name: 'Active', + negatedName: 'Inactive' + }, + { + type: 'field_value_toggle', + name: 'Mine', + field: 'owner', + value: 'dewey' + }, + { + type: 'field_value_selection', + field: 'tag', + name: 'Tag', + multiSelect: 'or', + cache: 10000, // will cache the loaded tags for 10 sec + options: () => loadTags() + } + ]; + + const schema = { + strict: true, + fields: { + active: { + type: 'boolean' + }, + status: { + type: 'string' + }, + followers: { + type: 'number' + }, + comments: { + type: 'number' + }, + stars: { + type: 'number' + }, + created: { + type: 'date' + }, + owner: { + type: 'string' + }, + tag: { + type: 'string', + validate: (value) => { + if (!tags.some(tag => tag.name === value)) { + throw new Error(`unknown tag (possible values: ${tags.map(tag => tag.name).join(',')})`); + } + } + } + } + }; + + return ( + + ); + } + + renderError() { + const { error } = this.state; + if (!error) { + return; + } + return ( + + + + + ); + } + + renderTable() { + const columns = [ + { + name: 'Type', + field: 'type' + }, + { + name: 'Open', + field: 'status', + render: (status) => status === 'open' ? 'Yes' : 'No' + }, + { + name: 'Active', + field: 'active', + dataType: 'boolean' + }, + { + name: 'Tags', + field: 'tag' + }, + { + name: 'Owner', + field: 'owner' + }, + { + name: 'Stats', + width: '150px', + render: (item) => { + return ( +
+
{`${item.stars} Stars`}
+
{`${item.followers} Followers`}
+
{`${item.comments} Comments`}
+
+ ); + } + } + ]; + + const queriedItems = EuiSearchBar.Query.execute(this.state.query, items, { + defaultFields: ['owner', 'tag', 'type'] + }); + + return ( + + ); + } + + render() { + const { + incremental, + } = this.state; + + const content = this.renderError() || ( + + + {this.renderTable()} + + + ); + + return ( + + + + {this.renderBookmarks()} + + + + + {this.renderSearch()} + + + + + + + + {content} + + ); + } +} diff --git a/src-docs/src/views/search_bar/props_info.js b/src-docs/src/views/search_bar/props_info.js index a6abf55c7a6..fc9bea07463 100644 --- a/src-docs/src/views/search_bar/props_info.js +++ b/src-docs/src/views/search_bar/props_info.js @@ -4,15 +4,10 @@ export const propsInfo = { __docgenInfo: { props: { onChange: { - description: 'Called every time the query behind the search bar changes', - required: true, - type: { name: '(query: #Query) => void' } - }, - onParse: { description: 'Called every time the text query in the search box is parsed. When parsing is successful ' + 'the callback will receive both the query text and the parsed query. When it fails ' + 'the callback ill receive the query text and an error object (holding the error message)', - required: false, + required: true, type: { name: '({ query?: #Query, queryText: string, error?: { message: string } }) => void' } }, query: { diff --git a/src-docs/src/views/search_bar/search_bar.js b/src-docs/src/views/search_bar/search_bar.js index 96d1b28f11e..9ef817d670a 100644 --- a/src-docs/src/views/search_bar/search_bar.js +++ b/src-docs/src/views/search_bar/search_bar.js @@ -77,16 +77,16 @@ export class SearchBar extends Component { }; } - onParse = ({ error }) => { - this.setState({ error }); - }; - - onChange = (query) => { - this.setState({ - error: null, - result: EuiSearchBar.Query.execute(query, items, { defaultFields: ['owner', 'tag', 'type'] }), - query - }); + onChange = ({ query, error }) => { + if (error) { + this.setState({ error }); + } else { + this.setState({ + error: null, + result: EuiSearchBar.Query.execute(query, items, { defaultFields: ['owner', 'tag', 'type'] }), + query + }); + } }; toggleIncremental = () => { @@ -178,7 +178,6 @@ export class SearchBar extends Component { }} filters={filters} onChange={this.onChange} - onParse={this.onParse} /> ); } diff --git a/src-docs/src/views/search_bar/search_bar_example.js b/src-docs/src/views/search_bar/search_bar_example.js index 89a91c79dcc..d3ec4fe8ece 100644 --- a/src-docs/src/views/search_bar/search_bar_example.js +++ b/src-docs/src/views/search_bar/search_bar_example.js @@ -12,10 +12,14 @@ import { } from '../../../../src/components'; import { SearchBar } from './search_bar'; +import { ControlledSearchBar } from './controlled_search_bar'; const searchBarSource = require('!!raw-loader!./search_bar'); const searchBarHtml = renderToHtml(SearchBar); +const controlledSearchBarSource = require('!!raw-loader!./controlled_search_bar'); +const controlledSearchBarHtml = renderToHtml(ControlledSearchBar); + export const SearchBarExample = { title: 'Search Bar', sections: [ @@ -89,6 +93,26 @@ export const SearchBarExample = { ), props: propsInfo, demo: + }, + { + title: 'Controlled Search Bar', + source: [ + { + type: GuideSectionTypes.JS, + code: controlledSearchBarSource, + }, { + type: GuideSectionTypes.HTML, + code: controlledSearchBarHtml, + } + ], + text: ( +
+

+ A EuiSearchBar can have its query controlled by a parent component by passing the `query` prop. Changes to the query will be passed back up through the onChange callback where the new Query must be stored in state and passed back into the search bar. +

+
+ ), + demo: } ], }; diff --git a/src/components/basic_table/in_memory_table.js b/src/components/basic_table/in_memory_table.js index 4c594747215..ce5e9937914 100644 --- a/src/components/basic_table/in_memory_table.js +++ b/src/components/basic_table/in_memory_table.js @@ -159,7 +159,7 @@ export class EuiInMemoryTable extends Component { }); }; - onQueryChange = (query) => { + onQueryChange = ({ query }) => { if (this.props.search.onChange) { const shouldQueryInMemory = this.props.search.onChange(query); if (!shouldQueryInMemory) { diff --git a/src/components/search_bar/search_bar.js b/src/components/search_bar/search_bar.js index c7a326d9d65..9e5a19a1b8e 100644 --- a/src/components/search_bar/search_bar.js +++ b/src/components/search_bar/search_bar.js @@ -16,15 +16,10 @@ import { EuiFlexItem } from '../flex/flex_item'; export const QueryType = PropTypes.oneOfType([ PropTypes.instanceOf(Query), PropTypes.string ]); export const SearchBarPropTypes = { - /** - * (query: Query) => void - */ - onChange: PropTypes.func, - /** (query?: Query, queryText: string, error?: string) => void */ - onParse: PropTypes.func, + onChange: PropTypes.func.isRequired, /** The initial query the bar will hold when first mounted @@ -56,12 +51,18 @@ export const SearchBarPropTypes = { /** * Tools which go to the right of the search bar. */ - toolsRight: PropTypes.node + toolsRight: PropTypes.node, + + /** + * Date formatter to use when parsing date values + */ + dateFormat: PropTypes.object }; const parseQuery = (query, props) => { const schema = props.box ? props.box.schema : undefined; - const parseOptions = { schema }; + const dateFormat = props.dateFormat; + const parseOptions = { schema, dateFormat }; if (!query) { return Query.parse('', parseOptions); } @@ -106,16 +107,7 @@ export class EuiSearchBar extends Component { const isErrorDifferent = oldError !== newError; if (isQueryDifferent || isErrorDifferent) { - if (this.props.onParse) { - this.props.onParse({ query, queryText, error }); - } - - // only fire onChange if there isn't an error - if (newError == null) { - if (this.props.onChange) { - this.props.onChange(query); - } - } + this.props.onChange({ query, queryText, error }); } } @@ -135,9 +127,6 @@ export class EuiSearchBar extends Component { queryText: query.text, error: null }); - if (this.props.onChange) { - this.props.onChange(query); - } }; renderTools(tools) { diff --git a/src/components/search_bar/search_bar.test.js b/src/components/search_bar/search_bar.test.js index 3a6bdf21bb9..861d9ada288 100644 --- a/src/components/search_bar/search_bar.test.js +++ b/src/components/search_bar/search_bar.test.js @@ -1,5 +1,5 @@ /* eslint-disable react/no-multi-comp */ -import React, { Component } from 'react'; +import React from 'react'; import { requiredProps } from '../../test'; import { mount, shallow } from 'enzyme'; import { EuiSearchBar } from './search_bar'; @@ -79,74 +79,49 @@ describe('SearchBar', () => { }); describe('controlled input', () => { - test('calls onParse callback when a new query is passed', () => { - const onParse = jest.fn(); + test('calls onChange callback when a new query is passed', () => { + const onChange = jest.fn(); - class Wrapper extends Component { - constructor(...args) { - super(...args); - this.state = { query: '' }; - } - - setQuery(query) { - this.setState({ query }); - } - - render() { - return ( - - ); - } - } const component = mount( - + ); - const wrapperInstance = component.instance(); - wrapperInstance.setQuery('is:active'); + component.setProps({ + ...requiredProps, + query: 'is:active', + onChange + }); - expect(onParse).toHaveBeenCalledTimes(1); - const [[{ query, queryText }]] = onParse.mock.calls; + expect(onChange).toHaveBeenCalledTimes(1); + const [[{ query, queryText }]] = onChange.mock.calls; expect(query).toBeInstanceOf(Query); expect(queryText).toBe('is:active'); }); - test('does not call onParse when an unwatched prop changes', () => { - const onParse = jest.fn(); + test('does not call onChange when an unwatched prop changes', () => { + const onChange = jest.fn(); - class Wrapper extends Component { - constructor(...args) { - super(...args); - this.state = { isFoo: false }; - } - - setIsFoo(isFoo) { - this.setState({ isFoo }); - } - - render() { - return ( - - ); - } - } const component = mount( - + ); - const wrapperInstance = component.instance(); - wrapperInstance.setIsFoo(true); + component.setProps({ + ...requiredProps, + query: 'is:active', + isFoo: true, + onChange + }); - expect(onParse).toHaveBeenCalledTimes(0); + expect(onChange).toHaveBeenCalledTimes(0); }); }); }); From 95bf58e350c2678617047238b4658dbb97c3fd9d Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Wed, 23 May 2018 12:53:19 -0600 Subject: [PATCH 6/6] some more cleanups --- CHANGELOG.md | 3 ++- .../src/views/search_bar/search_bar_example.js | 2 +- .../tables/in_memory/in_memory_search_callback.js | 2 +- src/components/basic_table/in_memory_table.js | 4 ++-- src/components/search_bar/search_bar.test.js | 15 ++------------- 5 files changed, 8 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c89e3826f9c..43e5a64233d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ **Breaking changes** -- `EuiSearchBar` no longer has an `onParse` callback, and now passes an object to `onChange` with the shape `{ query, queryText, error }` ([#863](https://github.com/elastic/eui/pull/863)) +- `EuiSearchBar` no longer has an `onParse` callback, and now passes an object to `onChange` with the shape `{ query, queryText, error }` ([#863](https://github.com/elastic/eui/pull/863)) +- `EuiInMemoryTable`'s `search.onChange` callback now passes an object with `{ query, queryText, error }` instead of only the query ([#863](https://github.com/elastic/eui/pull/863)) **Bug fixes** diff --git a/src-docs/src/views/search_bar/search_bar_example.js b/src-docs/src/views/search_bar/search_bar_example.js index d3ec4fe8ece..6be26cf0582 100644 --- a/src-docs/src/views/search_bar/search_bar_example.js +++ b/src-docs/src/views/search_bar/search_bar_example.js @@ -108,7 +108,7 @@ export const SearchBarExample = { text: (

- A EuiSearchBar can have its query controlled by a parent component by passing the `query` prop. Changes to the query will be passed back up through the onChange callback where the new Query must be stored in state and passed back into the search bar. + A EuiSearchBar can have its query controlled by a parent component by passing the query prop. Changes to the query will be passed back up through the onChange callback where the new Query must be stored in state and passed back into the search bar.

), 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 index 05a3ba8f695..5e8c4fc4ff4 100644 --- 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 @@ -44,7 +44,7 @@ export class Table extends React.Component { }; } - onQueryChange = query => { + onQueryChange = ({ query }) => { clearTimeout(debounceTimeoutId); clearTimeout(requestTimeoutId); diff --git a/src/components/basic_table/in_memory_table.js b/src/components/basic_table/in_memory_table.js index ce5e9937914..afe90b8f82e 100644 --- a/src/components/basic_table/in_memory_table.js +++ b/src/components/basic_table/in_memory_table.js @@ -159,9 +159,9 @@ export class EuiInMemoryTable extends Component { }); }; - onQueryChange = ({ query }) => { + onQueryChange = ({ query, queryText, error }) => { if (this.props.search.onChange) { - const shouldQueryInMemory = this.props.search.onChange(query); + const shouldQueryInMemory = this.props.search.onChange({ query, queryText, error }); if (!shouldQueryInMemory) { return; } diff --git a/src/components/search_bar/search_bar.test.js b/src/components/search_bar/search_bar.test.js index 861d9ada288..5e25eac0dca 100644 --- a/src/components/search_bar/search_bar.test.js +++ b/src/components/search_bar/search_bar.test.js @@ -84,17 +84,12 @@ describe('SearchBar', () => { const component = mount( ); - component.setProps({ - ...requiredProps, - query: 'is:active', - onChange - }); + component.setProps({ query: 'is:active' }); expect(onChange).toHaveBeenCalledTimes(1); const [[{ query, queryText }]] = onChange.mock.calls; @@ -107,19 +102,13 @@ describe('SearchBar', () => { const component = mount( ); - component.setProps({ - ...requiredProps, - query: 'is:active', - isFoo: true, - onChange - }); + component.setProps({ isFoo: true }); expect(onChange).toHaveBeenCalledTimes(0); });