Provide InputRange component valid value when Range slider is not set.#20002
Provide InputRange component valid value when Range slider is not set.#20002nreese merged 12 commits intoelastic:masterfrom
Conversation
💔 Build Failed |
39ac194 to
5243155
Compare
💔 Build Failed |
|
Looks like CI problems caused test failures because ES could not start jenkins, test this |
💔 Build Failed |
jenkins, test this |
💔 Build Failed |
5243155 to
aa8ad70
Compare
💔 Build Failed |
aa8ad70 to
e595b6c
Compare
💔 Build Failed |
|
jenkins, test this |
💚 Build Succeeded |
| let newValue = selectedOptions; | ||
| if (selectedOptions.length === 0) { | ||
| // control is empty | ||
| newValue = undefined; |
There was a problem hiding this comment.
instead of passing in undefined here, what about just passing in selectedOptions, as it was before, but having list_control.js (the business logic, not the component) override hasValue to check for an empty array, (or undefined too perhaps). Feels like this component having to understand what stageFilter would count as empty or not is leaking too much internal knowledge.
| @@ -115,7 +113,7 @@ export class Control { | |||
| } | |||
|
|
|||
| clear() { | |||
There was a problem hiding this comment.
|
|
||
| const toState = (props) => { | ||
| let sliderValue = props.control.value; | ||
| if (!props.control.value) { |
There was a problem hiding this comment.
should this be using hasValue as the check? Also looks like this function only uses props.control so no need to pass in the entire props.
chrisdavies
left a comment
There was a problem hiding this comment.
LGTM w/ the caveat that I agree w/ Stacey's comments. Nothing to add on top of those.
… comments about reset and clear functions
…l changes' as active for an empty form
💔 Build Failed |
|
jenkins, test this |
💚 Build Succeeded |
|
@stacey-gammon this is ready for another look |
| } | ||
| const state = { | ||
| sliderValue: props.control.value, | ||
| sliderValue: sliderValue, |
There was a problem hiding this comment.
nit: can be shortened to just sliderValue (https://github.com/airbnb/javascript#es6-object-concise)
| min: control.min, | ||
| max: control.min | ||
| }; | ||
| } |
There was a problem hiding this comment.
nit: could keep sliderValue as const via:
const sliderValue = control.hasValue() ?
control.value :
sliderValue = {
min: control.min,
max: control.min
};
| state.maxValue = props.control.value.max; | ||
| if (control.hasValue()) { | ||
| state.minValue = control.value.min; | ||
| state.maxValue = control.value.max; |
There was a problem hiding this comment.
nit: could make this a bit more concise via changing above:
...
minValue: control.hasValue() ? control.value.min : '',
maxValue: control.hasValue() ? control.value.max : '',
...
| */ | ||
| clear() { | ||
| this.set(this.filterManager.getUnsetValue()); | ||
| this.set(); |
There was a problem hiding this comment.
imo it'd be clearer to do this.value = undefined; Can set ever be called outside of clear with undefined? If not, we could throw an error in set if newValue is not defined (or when we eventually typescript we could tell then we don't support undefined), and then we don't have to check this.hasValue(), just always assume there is a value.
There was a problem hiding this comment.
We still need to support value being undefined to signal when the control is unset.
There was a problem hiding this comment.
I can't seem to trigger set being called with undefined outside of this clear function when playing around with the control. Can you tell me the instance you are referring to? Or maybe we are misunderstanding each other. I understand we need to support the value being undefined, I just mean writing the code like this would be clearer imo:
set(newValue) {
this.value = newValue;
this._kbnFilter = this.filterManager.createFilter(this.value);
}
clear() {
this.value = undefined;
this._kbnFilter = null;
}
Then when this supports typescript we can do something like set(newValue: T) instead of set(newValue: T | undefined)
There was a problem hiding this comment.
Here is a case where hasValue is needed. In the list control, when the list is cleared, set is called with []. In this case, _kbnFilter needs to be set to null since there is no filter value. This logic could move into filterManager.createFilter if that makes things easier to understand.
| } | ||
|
|
||
| hasValue() { | ||
| return this.value && this.value.length > 0; |
There was a problem hiding this comment.
I think there is a bug here. Looks like I can't set an input control drop down to false. Should probably be a hard check for undefined. Could you add a test that would have caught this issue when you fix it?
There was a problem hiding this comment.
The value can never be set to false. For list control, the value is either undefined or an array of objects with the shape label and value. I will create a test to show how the value gets set
There was a problem hiding this comment.
Ah, okay. I suppose I am hitting another bug. I created a list drop down with true and false values for the sample flight data set and I get:
Uncaught (in promise) Error: 0 is not a valid boolean value for boolean field Cancelled
at getConvertedValueForField (phrase.js:71)
at buildPhraseFilter (phrase.js:31)
at PhraseFilterManager.createFilter (phrase_filter_manager.js:72)
at ListControl.set (control.js:154)
at VisController._callee3$ (vis_controller.js:190)
at tryCatch (runtime.js:65)
at Generator.invoke [as _invoke] (runtime.js:303)
at Generator.prototype.(anonymous function) [as next] (http://localhost:5601/xmb/bundles/vendors.bundle.js:218445:21)
at step (vis_controller.js:41)
at vis_controller.js:41
at new Promise (<anonymous>)
at VisController.<anonymous> (vis_controller.js:41)
at VisController.stageFilter (vis_controller.js:218)
at ListControl._this.handleOnChange (list_control.js:64)
at EuiComboBox.onAddOption (combo_box.js:630)
at onOptionClick (combo_box.js:621)
Once we have this typescripted we can enforce that set on the base class is only ever called with a certain type, but as it is now, it's not clear that set should only be called with an array type or undefined. But I suppose this is fine as is for this PR.
There was a problem hiding this comment.
Would you mind creating a new issue for using boolean fields?
💔 Build Failed |
|
Test failure in unrelated area. jenkins, test this |
💔 Build Failed |
|
another unrelated test error jenkins, test this |
💚 Build Succeeded |
💚 Build Succeeded |
stacey-gammon
left a comment
There was a problem hiding this comment.
LGTM. Latest review was code only, pulled locally and tested on the prior commit.
elastic#20002) * move unsetLogic into react component * remove extra comment * add comment about why empty state is needed for InputRange component * fix broken jest test * move empty state logic from react component to ListControl class, add comments about reset and clear functions * add comments about clear and reset to control class * calculate hasChanged to avoid bug where clear form still shows 'cancel changes' as active for an empty form * use hasValue in range control to check if value exists * add unit test for list_control_factory and cleanup range_control from review comments
#20002) (#20735) * move unsetLogic into react component * remove extra comment * add comment about why empty state is needed for InputRange component * fix broken jest test * move empty state logic from react component to ListControl class, add comments about reset and clear functions * add comments about clear and reset to control class * calculate hasChanged to avoid bug where clear form still shows 'cancel changes' as active for an empty form * use hasValue in range control to check if value exists * add unit test for list_control_factory and cleanup range_control from review comments

fixes #19803
Move all unset logic out of control class and into react component where it is used.