Skip to content

Commit

Permalink
fix(live-component): fix array valued checkboxes change event handling
Browse files Browse the repository at this point in the history
  • Loading branch information
welcoMattic committed May 30, 2023
1 parent cec9422 commit b4ea936
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/LiveComponent/assets/dist/live_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ class ValueStore {
return this.pendingProps[normalizedName];
}
if (this.props[normalizedName] !== undefined) {
if (Array.isArray(this.props[normalizedName])) {
return [...this.props[normalizedName]];
}
return this.props[normalizedName];
}
return getDeepData(this.props, normalizedName);
Expand Down
3 changes: 3 additions & 0 deletions src/LiveComponent/assets/src/Component/ValueStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ export default class {
}

if (this.props[normalizedName] !== undefined) {
if (Array.isArray(this.props[normalizedName])) {
return [...this.props[normalizedName]];
}
return this.props[normalizedName];
}

Expand Down
62 changes: 62 additions & 0 deletions src/LiveComponent/assets/test/controller/model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,38 @@ describe('LiveController data-model Tests', () => {
expect(test.component.valueStore.getOriginalProps()).toEqual({form: {check: ['foo', 'bar']}});
});

it('sends correct data for array valued checkbox fields with non-form object', async () => {
const test = await createTest({ check: [] }, (data: any) => `
<div ${initComponent(data)}>
<form data-model="*">
<label>
Checkbox 1: <input type="checkbox" name="check[]" value="foo" ${data.check.indexOf('foo') > -1 ? 'checked' : ''} />
</label>
<label>
Checkbox 2: <input type="checkbox" name="check[]" value="bar" ${data.check.indexOf('bar') > -1 ? 'checked' : ''} />
</label>
</form>
Checkbox 2 is ${data.check.indexOf('bar') > -1 ? 'checked' : 'unchecked' }
</div>
`);

const check1Element = getByLabelText(test.element, 'Checkbox 1:');
const check2Element = getByLabelText(test.element, 'Checkbox 2:');

// only 1 Ajax call will be made thanks to debouncing
test.expectsAjaxCall()
.expectUpdatedData({ 'check': ['foo', 'bar'] });

await userEvent.click(check1Element);
await userEvent.click(check2Element);

await waitFor(() => expect(test.element).toHaveTextContent('Checkbox 2 is checked'));

expect(test.component.valueStore.getOriginalProps()).toEqual({check: ['foo', 'bar']});
});

it('sends correct data for array valued checkbox fields with initial data', async () => {
const test = await createTest({ form: { check: ['foo']} }, (data: any) => `
<div ${initComponent(data)}>
Expand Down Expand Up @@ -367,6 +399,36 @@ describe('LiveController data-model Tests', () => {
expect(test.component.valueStore.getOriginalProps()).toEqual({form: {check: ['bar']}});
});

it('sends correct data for array valued checkbox fields with non-form object and with initial data', async () => {
const test = await createTest({ check: ['foo'] }, (data: any) => `
<div ${initComponent(data)}>
<label>
Checkbox 1: <input type="checkbox" data-model="check[]" value="foo" ${data.check.indexOf('foo') > -1 ? 'checked' : ''} />
</label>
<label>
Checkbox 2: <input type="checkbox" data-model="check[]" value="bar" ${data.check.indexOf('bar') > -1 ? 'checked' : ''} />
</label>
Checkbox 1 is ${data.check.indexOf('foo') > -1 ? 'checked' : 'unchecked' }
</div>
`);

const check1Element = getByLabelText(test.element, 'Checkbox 1:');
const check2Element = getByLabelText(test.element, 'Checkbox 2:');

// only 1 Ajax call will be made thanks to debouncing
test.expectsAjaxCall()
.expectUpdatedData({ 'check': ['bar'] });

await userEvent.click(check1Element);
await userEvent.click(check2Element);

await waitFor(() => expect(test.element).toHaveTextContent('Checkbox 1 is unchecked'));

expect(test.component.valueStore.getOriginalProps()).toEqual({check: ['bar']});
});

it('sends correct data for select multiple field', async () => {
const test = await createTest({ form: { select: []} }, (data: any) => `
<div ${initComponent(data)}>
Expand Down

0 comments on commit b4ea936

Please sign in to comment.