diff --git a/changelog.md b/changelog.md index 98ab00863b..9bf2559fca 100644 --- a/changelog.md +++ b/changelog.md @@ -7,7 +7,7 @@ **What's Fixed** * [FiltersPanel]: set `undefined` value instead of `null` on clear action in numeric filter. * [ApiContext] Combine user's headers with internal ones instead of replacing them when calling `processRequest` function -* [LazyDataSource]: Fixed requesting already loaded data on scroll. +* [PickerList]: Fixed updating predefined checked values in PickerList. * [LazyDataSource]: Fixed requesting already loaded data on scroll. * [Pickers]: fixed infinite updating if onValueChange is called in useEffect (React components are rendered with render from 'react-dom'). diff --git a/uui-components/src/pickers/hooks/usePickerList.ts b/uui-components/src/pickers/hooks/usePickerList.ts index 57235b4949..4eb1b3f186 100644 --- a/uui-components/src/pickers/hooks/usePickerList.ts +++ b/uui-components/src/pickers/hooks/usePickerList.ts @@ -1,9 +1,10 @@ -import { useContext, useMemo } from 'react'; +import { useContext, useEffect, useMemo } from 'react'; import { DataRowProps, UuiContext } from '@epam/uui-core'; import { i18n } from '../../i18n'; import { usePicker } from './usePicker'; import { usePickerListState } from './usePickerListState'; import { UsePickerListProps } from './types'; +import { applyValueToDataSourceState, dataSourceStateToValue } from '../bindingHelpers'; interface LastUsedRec { id: TId; @@ -69,7 +70,7 @@ export function usePickerList(props: UsePickerListProps>(pickerProps, pickerListState); @@ -85,6 +86,19 @@ export function usePickerList(props: UsePickerListProps { + const prevValue = dataSourceStateToValue(props, dataSourceState, props.dataSource); + if (prevValue !== props.value) { + setDataSourceState((state) => + applyValueToDataSourceState( + props, + state, + props.value, + props.dataSource, + )); + } + }, [props.value]); + const onlySelectedView = props.dataSource.useView(getDataSourceState(), handleDataSourceValueChange, { rowOptions: getRowOptions(), getSearchFields: props.getSearchFields || ((item: TItem) => [getName(item)]), diff --git a/uui/components/pickers/__tests__/PickerList.test.tsx b/uui/components/pickers/__tests__/PickerList.test.tsx index c04b60c9b1..be53a7e11e 100644 --- a/uui/components/pickers/__tests__/PickerList.test.tsx +++ b/uui/components/pickers/__tests__/PickerList.test.tsx @@ -415,6 +415,38 @@ describe('PickerList', () => { }); }); + it('[valueType id] should update prechecked items', async () => { + const { mocks } = await setupPickerListForTest({ + value: [2], + selectionMode: 'multi', + }); + + await PickerListTestObject.waitForOptionsToBeReady(); + + expect(await PickerListTestObject.findCheckedOptions()).toEqual(['A1']); + + await PickerListTestObject.clickOptionCheckbox('A1+'); + await waitFor(() => { + expect(mocks.onValueChange).toHaveBeenLastCalledWith([2, 3]); + }); + + expect(await PickerListTestObject.findCheckedOptions()).toEqual(['A1', 'A1+']); + + const toggler = PickerListTestObject.getPickerToggler(); + fireEvent.click(toggler); + + await PickerListTestObject.waitForOptionsToBeReady('modal'); + + const checkedOptions1 = await PickerListTestObject.findCheckedOptions({ editMode: 'modal' }); + expect(checkedOptions1).toEqual(['A1', 'A1+']); + + await PickerListTestObject.clickOptionCheckbox('A1+', { editMode: 'modal' }); + await waitFor(async () => { + const checkedOptions2 = await PickerListTestObject.findCheckedOptions({ editMode: 'modal' }); + expect(checkedOptions2).toEqual(['A1']); + }); + }); + it('[valueType entity] should select & clear several options', async () => { const { mocks } = await setupPickerListForTest({ value: undefined,