[FIX] web: keep new widget el in ComponentAdapter
Before this commit, when sub widget replaced its el, the ComponentAdapter parent kept the previous el. This caused some issues as in the ActivityRecordAdapter which lost its event listeners when re-rendered. This commit forces the ComponentAdapter to keep the new sub widget el after being patched. task id: 2360021 closes odoo/odoo#60521 X-original-commit: 393b5fd4cfba254ad054a526996e82922f9057e2 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com> Signed-off-by: Michaël Mattiello <mcm-odoo@users.noreply.github.com>
This commit is contained in:
@@ -142,7 +142,11 @@ odoo.define('web.OwlCompatibility', function () {
|
||||
}
|
||||
vnode.elm = this.widget.el;
|
||||
}
|
||||
return super.__patch(...arguments);
|
||||
const result = super.__patch(...arguments);
|
||||
if (this.widget && this.el !== this.widget.el) {
|
||||
this.__owl__.vnode.elm = this.widget.el;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -680,6 +680,150 @@ odoo.define('web.OwlCompatibilityTests', function (require) {
|
||||
parent.destroy();
|
||||
});
|
||||
|
||||
QUnit.test("adapter keeps same el as sub widget (modify)", async function (assert) {
|
||||
assert.expect(7);
|
||||
|
||||
let myWidget;
|
||||
const MyWidget = Widget.extend({
|
||||
events: {
|
||||
click: "_onClick",
|
||||
},
|
||||
init: function (parent, name) {
|
||||
myWidget = this;
|
||||
this._super.apply(this, arguments);
|
||||
this.name = name;
|
||||
},
|
||||
start: function () {
|
||||
this.render();
|
||||
},
|
||||
render: function () {
|
||||
this.$el.text("Click me!");
|
||||
},
|
||||
update: function (name) {
|
||||
this.name = name;
|
||||
},
|
||||
_onClick: function () {
|
||||
assert.step(this.name);
|
||||
},
|
||||
});
|
||||
class MyWidgetAdapter extends ComponentAdapter {
|
||||
updateWidget(nextProps) {
|
||||
return this.widget.update(nextProps.name);
|
||||
}
|
||||
renderWidget() {
|
||||
this.widget.render();
|
||||
}
|
||||
}
|
||||
class Parent extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.MyWidget = MyWidget;
|
||||
this.state = useState({
|
||||
name: "GED",
|
||||
});
|
||||
}
|
||||
}
|
||||
Parent.template = xml`
|
||||
<MyWidgetAdapter Component="MyWidget" name="state.name"/>
|
||||
`;
|
||||
Parent.components = { MyWidgetAdapter };
|
||||
|
||||
const target = testUtils.prepareTarget();
|
||||
const parent = new Parent();
|
||||
await parent.mount(target);
|
||||
|
||||
assert.strictEqual(parent.el, myWidget.el);
|
||||
await testUtils.dom.click(parent.el);
|
||||
|
||||
parent.state.name = "AAB";
|
||||
await nextTick();
|
||||
|
||||
assert.strictEqual(parent.el, myWidget.el);
|
||||
await testUtils.dom.click(parent.el);
|
||||
|
||||
parent.state.name = "MCM";
|
||||
await nextTick();
|
||||
|
||||
assert.strictEqual(parent.el, myWidget.el);
|
||||
await testUtils.dom.click(parent.el);
|
||||
|
||||
assert.verifySteps(["GED", "AAB", "MCM"]);
|
||||
|
||||
parent.destroy();
|
||||
});
|
||||
|
||||
QUnit.test("adapter keeps same el as sub widget (replace)", async function (assert) {
|
||||
assert.expect(7);
|
||||
|
||||
let myWidget;
|
||||
const MyWidget = Widget.extend({
|
||||
events: {
|
||||
click: "_onClick",
|
||||
},
|
||||
init: function (parent, name) {
|
||||
myWidget = this;
|
||||
this._super.apply(this, arguments);
|
||||
this.name = name;
|
||||
},
|
||||
start: function () {
|
||||
this.render();
|
||||
},
|
||||
render: function () {
|
||||
this._replaceElement("<div>Click me!</div>");
|
||||
},
|
||||
update: function (name) {
|
||||
this.name = name;
|
||||
},
|
||||
_onClick: function () {
|
||||
assert.step(this.name);
|
||||
},
|
||||
});
|
||||
class MyWidgetAdapter extends ComponentAdapter {
|
||||
updateWidget(nextProps) {
|
||||
return this.widget.update(nextProps.name);
|
||||
}
|
||||
renderWidget() {
|
||||
this.widget.render();
|
||||
}
|
||||
}
|
||||
class Parent extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.MyWidget = MyWidget;
|
||||
this.state = useState({
|
||||
name: "GED",
|
||||
});
|
||||
}
|
||||
}
|
||||
Parent.template = xml`
|
||||
<MyWidgetAdapter Component="MyWidget" name="state.name"/>
|
||||
`;
|
||||
Parent.components = { MyWidgetAdapter };
|
||||
|
||||
const target = testUtils.prepareTarget();
|
||||
const parent = new Parent();
|
||||
await parent.mount(target);
|
||||
|
||||
assert.strictEqual(parent.el, myWidget.el);
|
||||
await testUtils.dom.click(parent.el);
|
||||
|
||||
parent.state.name = "AAB";
|
||||
await nextTick();
|
||||
|
||||
assert.strictEqual(parent.el, myWidget.el);
|
||||
await testUtils.dom.click(parent.el);
|
||||
|
||||
parent.state.name = "MCM";
|
||||
await nextTick();
|
||||
|
||||
assert.strictEqual(parent.el, myWidget.el);
|
||||
await testUtils.dom.click(parent.el);
|
||||
|
||||
assert.verifySteps(["GED", "AAB", "MCM"]);
|
||||
|
||||
parent.destroy();
|
||||
});
|
||||
|
||||
QUnit.module('WidgetAdapterMixin and ComponentWrapper');
|
||||
|
||||
QUnit.test("widget with sub component", async function (assert) {
|
||||
|
||||
Reference in New Issue
Block a user