summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
Diffstat (limited to 'addons')
-rw-r--r--addons/mail/static/src/widgets/form_renderer/form_renderer.js2
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js4
-rw-r--r--addons/web/static/src/js/views/form/form_renderer.js10
-rw-r--r--addons/web/static/tests/views/form_tests.js76
4 files changed, 88 insertions, 4 deletions
diff --git a/addons/mail/static/src/widgets/form_renderer/form_renderer.js b/addons/mail/static/src/widgets/form_renderer/form_renderer.js
index e4c3161c4da..cf147656d63 100644
--- a/addons/mail/static/src/widgets/form_renderer/form_renderer.js
+++ b/addons/mail/static/src/widgets/form_renderer/form_renderer.js
@@ -145,7 +145,7 @@ FormRenderer.include({
*
* @override
*/
- async _renderView() {
+ async __renderView() {
await this._super(...arguments);
if (this._hasChatter()) {
if (!this._chatterContainerComponent) {
diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js
index 16ecc473915..a03b9b41a77 100644
--- a/addons/web/static/src/js/views/basic/basic_renderer.js
+++ b/addons/web/static/src/js/views/basic/basic_renderer.js
@@ -684,7 +684,7 @@ var BasicRenderer = AbstractRenderer.extend(WidgetAdapterMixin, {
if (this._isInDom) {
for (const handle in this.allFieldWidgets) {
this.allFieldWidgets[handle].forEach(widget => {
- if (widget.on_attach_callback) {
+ if (!utils.isComponent(widget.constructor) && widget.on_attach_callback) {
widget.on_attach_callback();
}
});
@@ -694,6 +694,8 @@ var BasicRenderer = AbstractRenderer.extend(WidgetAdapterMixin, {
widget.on_attach_callback();
}
});
+ // call on_attach_callback on child components (including field components)
+ WidgetAdapterMixin.on_attach_callback.call(this);
}
},
/**
diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js
index b6e1593b215..c758c6a03fd 100644
--- a/addons/web/static/src/js/views/form/form_renderer.js
+++ b/addons/web/static/src/js/views/form/form_renderer.js
@@ -1029,7 +1029,7 @@ var FormRenderer = BasicRenderer.extend({
var $form = this._renderNode(this.arch).addClass(this.className);
delete this.defs;
- return Promise.all(defs).then(function () {
+ return Promise.all(defs).then(() => this.__renderView()).then(function () {
self._updateView($form.contents());
if (self.state.res_id in self.alertFields) {
self.displayTranslationAlert();
@@ -1043,6 +1043,14 @@ var FormRenderer = BasicRenderer.extend({
});
},
/**
+ * Meant to be overridden if asynchronous work needs to be done when
+ * rendering the view. This is called right before attaching the new view
+ * content.
+ * @private
+ * @returns {Promise<any>}
+ */
+ async __renderView() {},
+ /**
* This method is overridden to activate the first notebook page if the
* current active page is invisible due to modifiers. This is done after
* all modifiers are applied on all page elements.
diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js
index e0f179a4939..89d1797589d 100644
--- a/addons/web/static/tests/views/form_tests.js
+++ b/addons/web/static/tests/views/form_tests.js
@@ -1,12 +1,14 @@
odoo.define('web.form_tests', function (require) {
"use strict";
+const AbstractField = require("web.AbstractField");
var AbstractStorageService = require('web.AbstractStorageService');
var BasicModel = require('web.BasicModel');
var concurrency = require('web.concurrency');
var core = require('web.core');
var fieldRegistry = require('web.field_registry');
const fieldRegistryOwl = require('web.field_registry_owl');
+const FormRenderer = require('web.FormRenderer');
var FormView = require('web.FormView');
var mixins = require('web.mixins');
var NotificationService = require('web.NotificationService');
@@ -9666,9 +9668,81 @@ QUnit.module('Views', {
form.destroy();
delete fieldRegistryOwl.map.custom;
-
+
assert.verifySteps(['mounted', 'willUnmount']);
});
+
+ QUnit.test("attach callbacks with long processing in __renderView", async function (assert) {
+ /**
+ * The main use case of this test is discuss, in which the FormRenderer
+ * __renderView method is overridden to perform asynchronous tasks (the
+ * update of the chatter Component) resulting in a delay between the
+ * appending of the new form content into its element and the
+ * "on_attach_callback" calls. This is the purpose of "__renderView"
+ * which is meant to do all the async work before the content is appended.
+ */
+ assert.expect(11);
+
+ let testPromise = Promise.resolve();
+
+ const Renderer = FormRenderer.extend({
+ on_attach_callback() {
+ assert.step("form.on_attach_callback");
+ this._super(...arguments);
+ },
+ async __renderView() {
+ const _super = this._super.bind(this);
+ await testPromise;
+ return _super();
+ },
+ });
+
+ // Setup custom field widget
+ fieldRegistry.add("customwidget", AbstractField.extend({
+ className: "custom-widget",
+ on_attach_callback() {
+ assert.step("widget.on_attach_callback");
+ },
+ }));
+
+ const form = await createView({
+ arch: `<form><field name="bar" widget="customwidget"/></form>`,
+ data: this.data,
+ model: 'partner',
+ res_id: 1,
+ View: FormView.extend({
+ config: Object.assign({}, FormView.prototype.config, { Renderer }),
+ }),
+ });
+
+ assert.containsOnce(form, ".custom-widget");
+ assert.verifySteps([
+ "form.on_attach_callback", // Form attached
+ "widget.on_attach_callback", // Initial widget attached
+ ]);
+
+ const initialWidget = form.$(".custom-widget")[0];
+ testPromise = testUtils.makeTestPromise();
+
+ await testUtils.form.clickEdit(form);
+
+ assert.containsOnce(form, ".custom-widget");
+ assert.strictEqual(initialWidget, form.$(".custom-widget")[0], "Widgets have yet to be replaced");
+ assert.verifySteps([]);
+
+ testPromise.resolve();
+ await testUtils.nextTick();
+
+ assert.containsOnce(form, ".custom-widget");
+ assert.notStrictEqual(initialWidget, form.$(".custom-widget")[0], "Widgets have been replaced");
+ assert.verifySteps([
+ "widget.on_attach_callback", // New widget attached
+ ]);
+
+ form.destroy();
+
+ delete fieldRegistry.map.customwidget;
+ });
});
});