Skip to content

Commit 7b90f56

Browse files
committed
feature #1216 [Live] Throwing an error when setting an invalid model name (weaverryan)
This PR was merged into the 2.x branch. Discussion ---------- [Live] Throwing an error when setting an invalid model name | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | Tickets | From a Slack conversation | License | MIT Currently, if you use an invalid prop/model name in `data-model`, there is no error: the field is just silently *not* set. Now, we throw a clear error. It's possible (?) that people were relying on this - notably if someone is using a `<form data-model="*">` to auto-map every form field as a model... but only some exist on their component. However, 99% of the time people are using that with a Symfony form + `ComponentWithFormTrait`, where that will not be an issue. And I think if you have `data-model="*"`, you are saying that *every* field is a prop. For the sake of DX, we should fail loudly and not let users make accidents. Cheers! Commits ------- ed68c9c [Live] Throwing an error when setting an invalid model name
2 parents 1db34a8 + ed68c9c commit 7b90f56

File tree

3 files changed

+16
-1
lines changed

3 files changed

+16
-1
lines changed

src/LiveComponent/assets/dist/live_controller.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,6 +1799,9 @@ class Component {
17991799
set(model, value, reRender = false, debounce = false) {
18001800
const promise = this.nextRequestPromise;
18011801
const modelName = normalizeModelName(model);
1802+
if (!this.valueStore.has(modelName)) {
1803+
throw new Error(`Invalid model name "${model}".`);
1804+
}
18021805
const isChanged = this.valueStore.set(modelName, value);
18031806
this.hooks.triggerHook('model:set', model, value, this);
18041807
this.unsyncedInputsTracker.markModelAsSynced(modelName);

src/LiveComponent/assets/src/Component/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ export default class Component {
160160
set(model: string, value: any, reRender = false, debounce: number|boolean = false): Promise<BackendResponse> {
161161
const promise = this.nextRequestPromise;
162162
const modelName = normalizeModelName(model);
163+
164+
if (!this.valueStore.has(modelName)) {
165+
throw new Error(`Invalid model name "${model}".`);
166+
}
163167
const isChanged = this.valueStore.set(modelName, value);
164168

165169
this.hooks.triggerHook('model:set', model, value, this);

src/LiveComponent/assets/test/Component/index.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const makeTestComponent = (): { component: Component, backend: MockBackend } =>
2828
const component = new Component(
2929
document.createElement('div'),
3030
'test-component',
31-
{ firstName: '' },
31+
{ firstName: '', product: { name: '' } },
3232
[],
3333
() => [],
3434
null,
@@ -65,6 +65,14 @@ describe('Component class', () => {
6565
// @ts-ignore
6666
expect(await backendResponse?.getBody()).toEqual('<div data-live-props-value="{}"></div>');
6767
});
68+
69+
it('errors when an invalid model is passed', async () => {
70+
const { component } = makeTestComponent();
71+
72+
// setting nested - totally ok
73+
component.set('product.name', 'Ryan', false);
74+
expect(() => { component.set('notARealModel', 'Ryan', false) }).toThrow('Invalid model name "notARealModel"');
75+
});
6876
});
6977

7078
describe('Proxy wrapper', () => {

0 commit comments

Comments
 (0)