diff --git a/addons/web/static/src/core/code_editor/code_editor.js b/addons/web/static/src/core/code_editor/code_editor.js
index 99440acbd20..aecaab91ec4 100644
--- a/addons/web/static/src/core/code_editor/code_editor.js
+++ b/addons/web/static/src/core/code_editor/code_editor.js
@@ -62,6 +62,12 @@ export class CodeEditor extends Component {
onWillStart(async () => await loadBundle("web.ace_lib"));
const sessions = {};
+ // The ace library triggers the "change" event even if the change is
+ // programmatic. Even worse, it triggers 2 "change" events in that case,
+ // one with the empty string, and one with the new value. We only want
+ // to notify the parent of changes done by the user, in the UI, so we
+ // use this flag to filter out noisy "change" events.
+ let ignoredAceChange = false;
useEffect(
(el) => {
if (!el) {
@@ -85,7 +91,7 @@ export class CodeEditor extends Component {
}
aceEditor.setValue(this.props.value);
session.on("change", () => {
- if (this.props.onChange) {
+ if (this.props.onChange && !ignoredAceChange) {
this.props.onChange(this.aceEditor.getValue());
}
});
@@ -132,7 +138,9 @@ export class CodeEditor extends Component {
let session = sessions[sessionId];
if (session) {
if (session.getValue() !== value) {
+ ignoredAceChange = true;
session.setValue(value);
+ ignoredAceChange = false;
}
} else {
session = new window.ace.EditSession(value);
@@ -143,7 +151,7 @@ export class CodeEditor extends Component {
useSoftTabs: true,
});
session.on("change", () => {
- if (this.props.onChange) {
+ if (this.props.onChange && !ignoredAceChange) {
this.props.onChange(this.aceEditor.getValue());
}
});
diff --git a/addons/web/static/tests/core/code_editor_tests.js b/addons/web/static/tests/core/code_editor_tests.js
index f11aa035b19..cd37b6e104d 100644
--- a/addons/web/static/tests/core/code_editor_tests.js
+++ b/addons/web/static/tests/core/code_editor_tests.js
@@ -128,6 +128,27 @@ QUnit.module("Web Components", (hooks) => {
assert.verifySteps(["Some Text"], "Value properly given to onChange");
});
+ QUnit.test("onChange props not called when value props is updated", async (assert) => {
+ class Parent extends Component {
+ static components = { CodeEditor };
+ static template = xml`
A Paragraph
\nAn Other Paragraph
\n