Skip to content

Commit 74ad422

Browse files
committed
[Live] Fixing a bug where parent component model would be used to set child model field
1 parent 6040306 commit 74ad422

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

src/LiveComponent/assets/dist/live_controller.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,9 @@ class SetValueOntoModelFieldsPlugin {
21122112
if (element instanceof HTMLFormElement) {
21132113
return;
21142114
}
2115+
if (!elementBelongsToThisComponent(element, component)) {
2116+
return;
2117+
}
21152118
const modelDirective = getModelDirectiveFromElement(element);
21162119
if (!modelDirective) {
21172120
return;

src/LiveComponent/assets/src/Component/plugins/SetValueOntoModelFieldsPlugin.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Component from '../index';
22
import {
3+
elementBelongsToThisComponent,
34
getModelDirectiveFromElement,
45
getValueFromElement,
56
setValueOnElement
@@ -38,6 +39,10 @@ export default class implements PluginInterface {
3839
return;
3940
}
4041

42+
if (!elementBelongsToThisComponent(element, component)) {
43+
return;
44+
}
45+
4146
const modelDirective = getModelDirectiveFromElement(element);
4247
if (!modelDirective) {
4348
return;

src/LiveComponent/assets/test/controller/model.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,45 @@ describe('LiveController data-model Tests', () => {
628628
expect(commentField.value).toEqual('MMMM SO GOOD');
629629
});
630630

631+
it('does not try to set the value of inputs inside a child component', async () => {
632+
const test = await createTest({ comment: 'cookie', childComment: 'mmmm' }, (data: any) => `
633+
<div ${initComponent(data)}>
634+
<textarea data-model="comment" id="parent-comment"></textarea>
635+
636+
<div ${initComponent({ comment: data.childComment }, {}, {id: 'the-child-id'})}>
637+
<textarea data-model="comment" id="child-comment"></textarea>
638+
</div>
639+
</div>
640+
`);
641+
642+
const commentField = test.element.querySelector('#parent-comment');
643+
if (!(commentField instanceof HTMLTextAreaElement)) {
644+
throw new Error('wrong type');
645+
}
646+
expect(commentField.value).toEqual('cookie');
647+
648+
const childCommentField = test.element.querySelector('#child-comment');
649+
if (!(childCommentField instanceof HTMLTextAreaElement)) {
650+
throw new Error('wrong type');
651+
}
652+
expect(childCommentField.value).toEqual('mmmm');
653+
654+
// NOW we will re-render
655+
test.expectsAjaxCall('get')
656+
.expectSentData(test.initialData)
657+
// change the data to be extra tricky
658+
.serverWillChangeData((data) => {
659+
data.comment = 'i like apples';
660+
})
661+
.init();
662+
663+
await test.component.render();
664+
665+
expect(commentField.value).toEqual('i like apples');
666+
// child component should not have been re-rendered
667+
expect(childCommentField.value).toEqual('mmmm');
668+
});
669+
631670
it('keeps the unsynced value of an input on re-render, but accepts other changes to the field', async () => {
632671
const test = await createTest({
633672
comment: 'Live components',

0 commit comments

Comments
 (0)