From 3400667a015c96f616f0c18e9306308b14b6054c Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Wed, 15 Jan 2020 21:23:26 -0700 Subject: [PATCH] Fix EuiFieldSearch's onChange call so it is always called with the Event (#2764) * Fix EuiFieldSearch's onChange call so it is always called with the Event * changelog * Actually trigger the browser's change event handling --- CHANGELOG.md | 4 ++- .../src/views/form_controls/field_search.js | 2 +- .../form/field_search/field_search.js | 32 ++++++++++++++++++- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96d58518cc5..38ff588000b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## [`master`](https://github.com/elastic/eui/tree/master) -No public interface changes since `18.2.0`. +**Bug fixes** + +- Fixed `EuiFieldSearch`'s trigger of `onChange` when clearing the field value ([#2764](https://github.com/elastic/eui/pull/2764)) ## [`18.2.0`](https://github.com/elastic/eui/tree/v18.2.0) diff --git a/src-docs/src/views/form_controls/field_search.js b/src-docs/src/views/form_controls/field_search.js index 14afc92027e..22dc0fd3960 100644 --- a/src-docs/src/views/form_controls/field_search.js +++ b/src-docs/src/views/form_controls/field_search.js @@ -15,7 +15,7 @@ export default class extends Component { onChange = e => { this.setState({ - value: e === '' ? '' : e.target.value, + value: e.target.value, }); }; diff --git a/src/components/form/field_search/field_search.js b/src/components/form/field_search/field_search.js index f9acc8d706b..580c36c3520 100644 --- a/src/components/form/field_search/field_search.js +++ b/src/components/form/field_search/field_search.js @@ -69,7 +69,37 @@ export class EuiFieldSearch extends Component { } onClear = () => { - this.props.onChange(''); + // clear the field's value + + // 1. React doesn't listen for `change` events, instead it maps `input` events to `change` + // 2. React only fires the mapped `change` event if the element's value has changed + // 3. An input's value is, in addition to other methods, tracked by intercepting element.value = '...' + // + // So we have to go below the element's value setter to avoid React intercepting it, + // only then will React treat the value as different and fire its `change` event + // + // https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js + const nativeInputValueSetter = Object.getOwnPropertyDescriptor( + window.HTMLInputElement.prototype, + 'value' + ).set; + nativeInputValueSetter.call(this.inputElement, ''); + + // dispatch input event, with IE11 support/fallback + if ('Event' in window && typeof Event === 'function') { + const event = new Event('input', { + bubbles: true, + cancelable: false, + }); + this.inputElement.dispatchEvent(event); + } else { + // IE11 + const event = document.createEvent('Event'); + event.initEvent('input', true, false); + this.inputElement.dispatchEvent(event); + } + + // set focus on the search field this.inputElement.focus(); };