diff --git a/addons/mail/static/src/js/onchange_on_keydown.js b/addons/mail/static/src/js/onchange_on_keydown.js index af400e12385..a6901bc8b4c 100644 --- a/addons/mail/static/src/js/onchange_on_keydown.js +++ b/addons/mail/static/src/js/onchange_on_keydown.js @@ -1,9 +1,9 @@ /* @odoo-module */ import { patch } from "@web/core/utils/patch"; -import { debounce } from "@web/core/utils/timing"; -import { CharField, charField } from "@web/views/fields/char/char_field"; -import { TextField, textField } from "@web/views/fields/text/text_field"; +import { useDebounced } from "@web/core/utils/timing"; +import { charField, CharField } from "@web/views/fields/char/char_field"; +import { textField, TextField } from "@web/views/fields/text/text_field"; import { archParseBoolean } from "@web/views/utils"; const { useEffect } = owl; @@ -21,10 +21,16 @@ const onchangeOnKeydownMixin = () => ({ if (this.props.onchangeOnKeydown) { const input = this.input || this.textareaRef; - const triggerOnChange = debounce(this.triggerOnChange, this.props.keydownDebounceDelay); + const triggerOnChange = useDebounced( + this.triggerOnChange, + this.props.keydownDebounceDelay + ); useEffect(() => { if (input.el) { - input.el.addEventListener("keydown", triggerOnChange.bind(this)); + input.el.addEventListener("keydown", triggerOnChange); + return () => { + input.el.removeEventListener("keydown", triggerOnChange); + }; } }); } diff --git a/addons/mail/static/tests/web/fields/onchange_on_keydown_tests.js b/addons/mail/static/tests/web/fields/onchange_on_keydown_tests.js index eeca0820a6d..36e54cad037 100644 --- a/addons/mail/static/tests/web/fields/onchange_on_keydown_tests.js +++ b/addons/mail/static/tests/web/fields/onchange_on_keydown_tests.js @@ -1,24 +1,34 @@ /* @odoo-module */ -import { nextTick } from "@web/../tests/helpers/utils"; +import { + editInput, + getFixture, + mockTimeout, + nextTick, + triggerEvent, +} from "@web/../tests/helpers/utils"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; import { dom } from "@web/../tests/legacy/helpers/test_utils"; let serverData; +let target; QUnit.module("onchange on keydown", { async beforeEach() { + target = getFixture(); serverData = { models: { "res.partner": { fields: { id: { type: "integer" }, description: { type: "text" }, + display_name: { type: "char" }, }, records: [ { id: 1, description: "", + display_name: "first record", }, ], onchanges: { @@ -74,3 +84,31 @@ QUnit.test( await nextTick(); } ); + +QUnit.test( + "Editing a text field with the onchange_on_keydown option disappearing shouldn't trigger a crash", + async function (assert) { + const { execRegisteredTimeouts } = mockTimeout(); + await makeView({ + type: "form", + resModel: "res.partner", + serverData, + resId: 1, + arch: ` +
+ + + `, + mockRPC(route, params) { + if (params.method === "onchange") { + assert.step("onchange"); + } + }, + }); + + await triggerEvent(target, 'textarea[id="description_0"]', "keydown", { key: "a" }); + await editInput(target, "[name=display_name] input", "yop"); + await execRegisteredTimeouts(); + assert.verifySteps([]); + } +);