Skip to content

Commit e022dc9

Browse files
committed
fix(common): make props to control deselection of values
1 parent f21694c commit e022dc9

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

packages/common/src/select/index.js

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const Select = ({
4040
value,
4141
onChange,
4242
loadOptionsChangeCounter,
43+
noValueUpdates,
4344
...props
4445
}) => {
4546
const [state, dispatch] = useReducer(reducer, {
@@ -56,13 +57,15 @@ const Select = ({
5657

5758
return loadOptions().then((data) => {
5859
if (isMounted) {
59-
if (value && Array.isArray(value)) {
60-
const selectValue = value.filter((value) =>
61-
typeof value === 'object' ? data.find((option) => value.value === option.value) : data.find((option) => value === option.value)
62-
);
63-
onChange(selectValue.length === 0 ? undefined : selectValue);
64-
} else if (value && !data.find(({ value: internalValue }) => internalValue === value)) {
65-
onChange(undefined);
60+
if (!noValueUpdates) {
61+
if (value && Array.isArray(value)) {
62+
const selectValue = value.filter((value) =>
63+
typeof value === 'object' ? data.find((option) => value.value === option.value) : data.find((option) => value === option.value)
64+
);
65+
onChange(selectValue.length === 0 ? undefined : selectValue);
66+
} else if (value && !data.find(({ value: internalValue }) => internalValue === value)) {
67+
onChange(undefined);
68+
}
6669
}
6770

6871
dispatch({ type: 'updateOptions', payload: data });
@@ -88,7 +91,7 @@ const Select = ({
8891

8992
useEffect(() => {
9093
if (state.isInitialLoaded) {
91-
if (value && !propsOptions.map(({ value }) => value).includes(value)) {
94+
if (!noValueUpdates && value && !propsOptions.map(({ value }) => value).includes(value)) {
9295
onChange(undefined);
9396
}
9497

@@ -176,7 +179,8 @@ Select.propTypes = {
176179
selectVariant: PropTypes.string,
177180
updatingMessage: PropTypes.node,
178181
noOptionsMessage: PropTypes.node,
179-
isSearchable: PropTypes.bool
182+
isSearchable: PropTypes.bool,
183+
noValueUpdates: PropTypes.bool
180184
};
181185

182186
Select.defaultProps = {

packages/pf3-component-mapper/src/tests/form-fields/select/select.test.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,15 @@ describe('<SelectField />', () => {
164164
expect(changeSpy).toHaveBeenCalledWith(undefined);
165165
});
166166

167+
it('should not change the value when new options do not include it and noValueUpdates is set', () => {
168+
const wrapper = mount(<Wrapper {...initialProps} noValueUpdates input={{ ...initialProps.input, value: 1 }} />);
169+
170+
wrapper.setProps({ options: NEW_OPTIONS });
171+
wrapper.update();
172+
173+
expect(changeSpy).not.toHaveBeenCalled();
174+
});
175+
167176
it('not should change the value when new options include it', () => {
168177
const wrapper = mount(<Wrapper {...initialProps} input={{ ...initialProps.input, value: 2 }} />);
169178

@@ -189,7 +198,23 @@ describe('<SelectField />', () => {
189198
});
190199
});
191200

192-
it('should reset the value when loadOptions prop is changed and new options do not include the value', (done) => {
201+
it('should not reset the value when loadOptions prop is changed and new options do not include the value - noValueUpdates is set', (done) => {
202+
const wrapper = mount(<Wrapper {...initialProps} noValueUpdates loadOptions={asyncLoading} input={{ ...initialProps.input, value: 1 }} />);
203+
204+
setImmediate(() => {
205+
wrapper.update();
206+
wrapper.setProps({ loadOptions: asyncLoadingNew });
207+
208+
setImmediate(() => {
209+
wrapper.update();
210+
211+
expect(changeSpy).not.toHaveBeenCalledWith();
212+
done();
213+
});
214+
});
215+
});
216+
217+
it('should not reset the value when loadOptions prop is changed and new options include the value', (done) => {
193218
const wrapper = mount(<Wrapper {...initialProps} loadOptions={asyncLoading} input={{ ...initialProps.input, value: 2 }} />);
194219

195220
setImmediate(() => {

packages/react-renderer-demo/src/app/src/doc-components/pf3-select.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ PF3 Select allows to load the options asynchronously.
66
|---------|----|-----------|
77
|loadOptions|`func`|A function returning `Promise`, only on mount.|
88
|loadingMessage|`string`|A message shown during the loading.|
9+
|noValueUpdates|`bool`|When set on true, the select won't deselect values not found in options.|
910

1011
**loadOptions example**
1112

packages/react-renderer-demo/src/app/src/doc-components/pf4-select.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ PF4 Select allows to load the options asynchronously.
1515
|loadOptions|`func`|A function returning `Promise`: `(searchValue) => new Promise`|
1616
|loadingMessage|`node`|A message shown during the initial loading.|
1717
|updatingMessage|`node`|A message shown during the loading|
18+
|noValueUpdates|`bool`|When set on true, the select won't deselect values not found in options.|
1819

1920
**loadOptions example**
2021

0 commit comments

Comments
 (0)