Skip to content

Commit 429ca69

Browse files
committed
fixed new value set by form context is not rendered properly by RruMultiCheckboxInput, RruMultiSelectInput, RruRadioInput, and RruSelectInput.
1 parent 7364270 commit 429ca69

File tree

6 files changed

+39
-34
lines changed

6 files changed

+39
-34
lines changed

src/form/RruMultiCheckboxInput/RruMultiCheckboxInput.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,16 @@ import { findOptions, isOptionsGroup } from '../utils/options-utils';
2424
import RruMultiCheckboxInputProps from './types/RruMultiCheckboxInputProps';
2525

2626
const RruMultiCheckboxInput: FC<RruMultiCheckboxInputProps> = (props) => {
27-
const [value, setValue] = useState<string | null>(null);
27+
const [hasBeenInitialized, setHasBeenInitialized] = useState<boolean>(false);
28+
const [selectedOptions, setSelectedOptions] = useState<readonly RruOption[]>([]);
2829

2930
const field = useField(props.name, (serializedValue) => {
30-
if (!deepEqual(serializedValue, value)) {
31-
setValue(serializedValue);
31+
if (!deepEqual(serializedValue, selectedOptions.map(o => o.value))) {
32+
const options = findOptions(props.options, serializedValue || []);
33+
setSelectedOptions(options);
3234
}
3335
});
3436

35-
const [hasBeenInitialized, setHasBeenInitialized] = useState<boolean>(false);
36-
const [selectedOptions, setSelectedOptions] = useState<readonly RruOption[]>([]);
37-
3837
const onSelectChange = (options: readonly RruOption[]) => {
3938
setSelectedOptions(options);
4039
field.setValue(options.map((opt) => opt.value));
@@ -106,7 +105,7 @@ const RruMultiCheckboxInput: FC<RruMultiCheckboxInputProps> = (props) => {
106105
<div
107106
className='form-group'
108107
data-field-name={props.name}
109-
data-field-value={value}
108+
data-field-value={selectedOptions.map(o => o.value).toSorted()}
110109
data-field-error={field.error ? field.error.message : ''}
111110
>
112111
<Label label={props.label} requiredAsterisk={props.requiredAsterisk}></Label>

src/form/RruMultiSelectInput/RruMultiSelectInput.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,16 @@ import { findOptions, loadPageOptions } from '../utils/options-utils';
2626
import RruMultiSelectInputProps from './types/RruMultiSelectInputProps';
2727

2828
const RruMultiSelectInput: FC<RruMultiSelectInputProps> = (props) => {
29-
const [value, setValue] = useState<string | null>(null);
29+
const [hasBeenInitialized, setHasBeenInitialized] = useState<boolean>(false);
30+
const [selectedOptions, setSelectedOptions] = useState<readonly RruOption[]>([]);
3031

3132
const field = useField(props.name, (serializedValue) => {
32-
if (!deepEqual(serializedValue, value)) {
33-
setValue(serializedValue);
33+
if (!deepEqual(serializedValue, selectedOptions.map(o => o.value))) {
34+
const options = findOptions(props.options, serializedValue || []);
35+
setSelectedOptions(options);
3436
}
3537
});
3638

37-
const [hasBeenInitialized, setHasBeenInitialized] = useState<boolean>(false);
38-
const [selectedOptions, setSelectedOptions] = useState<readonly RruOption[]>([]);
39-
4039
const onSelectChange = (options: readonly RruOption[]) => {
4140
setSelectedOptions(options);
4241
field.setValue(options.map((opt) => opt.value));
@@ -81,7 +80,7 @@ const RruMultiSelectInput: FC<RruMultiSelectInputProps> = (props) => {
8180
<div
8281
className='form-group'
8382
data-field-name={props.name}
84-
data-field-value={value}
83+
data-field-value={selectedOptions.map(o => o.value).toSorted()}
8584
data-field-error={field.error ? field.error.message : ''}
8685
>
8786
<Label label={props.label} requiredAsterisk={props.requiredAsterisk}></Label>

src/form/RruRadioInput/RruRadioInput.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ import { findOption, isOptionsGroup } from '../utils/options-utils';
2424
import RruRadioInputProps from './types/RruRadioInputProps';
2525

2626
const RruRadioInput: FC<RruRadioInputProps> = (props) => {
27-
const [value, setValue] = useState<string | null>(null);
27+
const [hasBeenInitialized, setHasBeenInitialized] = useState<boolean>(false);
28+
const [selectedOption, setSelectedOption] = useState<RruOption | null>(null);
2829

2930
const field = useField(props.name, (serializedValue) => {
30-
if (!deepEqual(serializedValue, value)) {
31-
setValue(serializedValue);
31+
if (!deepEqual(serializedValue, selectedOption?.value)) {
32+
const option = findOption(props.options, serializedValue);
33+
setSelectedOption(option);
3234
}
3335
});
3436

35-
const [hasBeenInitialized, setHasBeenInitialized] = useState<boolean>(false);
36-
const [selectedOption, setSelectedOption] = useState<RruOption | null>(null);
3737

3838
const onSelectChange = (option: RruOption | null) => {
3939
setSelectedOption(option);
@@ -93,7 +93,7 @@ const RruRadioInput: FC<RruRadioInputProps> = (props) => {
9393
<div
9494
className='form-group'
9595
data-field-name={props.name}
96-
data-field-value={value}
96+
data-field-value={selectedOption?.value}
9797
data-field-error={field.error ? field.error.message : ''}
9898
>
9999
<Label label={props.label} requiredAsterisk={props.requiredAsterisk}></Label>

src/form/RruSelectInput/RruSelectInput.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,16 @@ import { findOption, loadPageOptions } from '../utils/options-utils';
2626
import RruSelectInputProps from './types/RruSelectInputProps';
2727

2828
const RruSelectInput: FC<RruSelectInputProps> = (props) => {
29-
const [value, setValue] = useState<string | null>(null);
29+
const [hasBeenInitialized, setHasBeenInitialized] = useState<boolean>(false);
30+
const [selectedOption, setSelectedOption] = useState<RruOption | null>(null);
3031

3132
const field = useField(props.name, (serializedValue) => {
32-
if (!deepEqual(serializedValue, value)) {
33-
setValue(serializedValue);
33+
if (!deepEqual(serializedValue, selectedOption?.value)) {
34+
const option = findOption(props.options, serializedValue);
35+
setSelectedOption(option);
3436
}
3537
});
3638

37-
const [hasBeenInitialized, setHasBeenInitialized] = useState<boolean>(false);
38-
const [selectedOption, setSelectedOption] = useState<RruOption | null>(null);
39-
4039
const onSelectChange = (option: RruOption | null) => {
4140
setSelectedOption(option);
4241
field.setValue(option ? option.value : null);
@@ -78,7 +77,7 @@ const RruSelectInput: FC<RruSelectInputProps> = (props) => {
7877
<div
7978
className='form-group'
8079
data-field-name={props.name}
81-
data-field-value={value}
80+
data-field-value={selectedOption?.value}
8281
data-field-error={field.error ? field.error.message : ''}
8382
>
8483
<Label label={props.label} requiredAsterisk={props.requiredAsterisk}></Label>

src/utils/utils.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,18 @@ const resolveObjectAttribute = (path: string, obj: object): any => {
7373
return cur;
7474
}
7575

76-
const deepEqual = (x: any, y: any): boolean => {
77-
const ok = Object.keys,
78-
tx = typeof x,
79-
ty = typeof y;
76+
const deepEqual = (x: unknown, y: unknown): boolean => {
77+
const ok = Object.keys;
78+
const tx = typeof x
79+
const ty = typeof y;
80+
81+
if(Array.isArray(x)){
82+
x = x.toSorted();
83+
}
84+
85+
if(Array.isArray(y)){
86+
y = y.toSorted();
87+
}
8088

8189
return x && y && tx === 'object' && tx === ty
8290
? ok(x).length === ok(y).length && ok(x).every((key) => deepEqual(x[key], y[key]))

tests/__utils__/form-utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export const expectSelectedOptionIsRendered = (container: HTMLElement, fieldName
8888
expect(fieldContainer).toBeTruthy();
8989

9090
// this is just a data attribute
91-
expect(fieldContainer!.getAttribute(`data-field-value`)).toBe(isMultiple ? optionValue.join(',') : optionValue);
91+
expect(fieldContainer!.getAttribute(`data-field-value`)).toBe(isMultiple ? optionValue.toSorted().join(',') : optionValue);
9292

9393
// this is what actually the user sees
9494
const fieldInputs = fieldContainer!.querySelectorAll(`input[name="${fieldName}"]`);
@@ -128,7 +128,7 @@ export const expectSelectedRadioOptionIsRendered = (container: HTMLElement, fiel
128128
expect(fieldContainer).toBeTruthy();
129129

130130
// this is just a data attribute
131-
expect(fieldContainer!.getAttribute(`data-field-value`)).toBe(isMultiple ? optionValue.join(',') : optionValue);
131+
expect(fieldContainer!.getAttribute(`data-field-value`)).toBe(isMultiple ? optionValue.toSorted().join(',') : optionValue);
132132

133133
// this is what actually the user sees
134134
const fieldInput = fieldContainer!.querySelector(`input[name="${fieldName}"][type="radio"][value="${optionValue}"]`);
@@ -157,7 +157,7 @@ export const expectSelectedMultipleCheckboxOptionsAreRendered = (container: HTML
157157
expect(fieldContainer).toBeTruthy();
158158

159159
// this is just a data attribute
160-
expect(fieldContainer!.getAttribute(`data-field-value`)).toBe(optionValue.join(','));
160+
expect(fieldContainer!.getAttribute(`data-field-value`)).toBe(optionValue.toSorted().join(','));
161161

162162
// this is what actually the user sees
163163
const fieldInputs = fieldContainer!.querySelectorAll(`input[name="${fieldName}"][type="checkbox"]`);

0 commit comments

Comments
 (0)