diff --git a/src/LiveComponent/assets/dist/live_controller.js b/src/LiveComponent/assets/dist/live_controller.js index 425b2e6a90b..8bea5c1985e 100644 --- a/src/LiveComponent/assets/dist/live_controller.js +++ b/src/LiveComponent/assets/dist/live_controller.js @@ -1799,6 +1799,9 @@ class Component { set(model, value, reRender = false, debounce = false) { const promise = this.nextRequestPromise; const modelName = normalizeModelName(model); + if (!this.valueStore.has(modelName)) { + throw new Error(`Invalid model name "${model}".`); + } const isChanged = this.valueStore.set(modelName, value); this.hooks.triggerHook('model:set', model, value, this); this.unsyncedInputsTracker.markModelAsSynced(modelName); diff --git a/src/LiveComponent/assets/src/Component/index.ts b/src/LiveComponent/assets/src/Component/index.ts index f3c22905f8a..687ed7a2c65 100644 --- a/src/LiveComponent/assets/src/Component/index.ts +++ b/src/LiveComponent/assets/src/Component/index.ts @@ -160,6 +160,10 @@ export default class Component { set(model: string, value: any, reRender = false, debounce: number|boolean = false): Promise { const promise = this.nextRequestPromise; const modelName = normalizeModelName(model); + + if (!this.valueStore.has(modelName)) { + throw new Error(`Invalid model name "${model}".`); + } const isChanged = this.valueStore.set(modelName, value); this.hooks.triggerHook('model:set', model, value, this); diff --git a/src/LiveComponent/assets/test/Component/index.test.ts b/src/LiveComponent/assets/test/Component/index.test.ts index 8a558dbc071..27ffafb58ec 100644 --- a/src/LiveComponent/assets/test/Component/index.test.ts +++ b/src/LiveComponent/assets/test/Component/index.test.ts @@ -28,7 +28,7 @@ const makeTestComponent = (): { component: Component, backend: MockBackend } => const component = new Component( document.createElement('div'), 'test-component', - { firstName: '' }, + { firstName: '', product: { name: '' } }, [], () => [], null, @@ -65,6 +65,14 @@ describe('Component class', () => { // @ts-ignore expect(await backendResponse?.getBody()).toEqual('
'); }); + + it('errors when an invalid model is passed', async () => { + const { component } = makeTestComponent(); + + // setting nested - totally ok + component.set('product.name', 'Ryan', false); + expect(() => { component.set('notARealModel', 'Ryan', false) }).toThrow('Invalid model name "notARealModel"'); + }); }); describe('Proxy wrapper', () => {