summaryrefslogtreecommitdiff
path: root/addons/web/static
diff options
context:
space:
mode:
authorNicolas Lempereur <nle@odoo.com>2020-06-23 16:43:29 +0000
committerNicolas Lempereur <nle@odoo.com>2020-06-24 15:48:27 +0000
commite961a2fe0998860f051a8ef585dd619b8a7dadda (patch)
tree892ad3d7c8f23338a12da298f699fff770adfc4a /addons/web/static
parent446888cc0d8023c771e7fe2a8ea1be501619b39d (diff)
[FIX] web: action before field willStart end
On a re-render, when: - a field is not yet started (still in willStart because of RPC) - then an action is executed we can get a traceback because we try to save the field before it is started and `this.el` is not set. eg. in MRP on a work order: - click on + to get new serial number => page is re-rendered with RPC call to update duration to mrp.workcenter.productivity().search_read to update time counter - click on "Record production" before RPC is finished => traceback because we try to save `duration` that is not already started (`this.$el.toggleClass` when `this.$el` is `undefined`) Without change, added test fails with: "Cannot read property 'toggleClass' of undefined" in BasicRenderer.canBeSaved "Expected 6 assertions, but 5 were run" Before saas-11.3 5faec34a3c this.el was always set in `init` so this issue did not happen. opw-2272117 closes #53532 closes odoo/odoo#53612 X-original-commit: befcad51fd236fdaf284f76cea5624d21c070b0e Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
Diffstat (limited to 'addons/web/static')
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js6
-rw-r--r--addons/web/static/tests/views/form_tests.js58
2 files changed, 62 insertions, 2 deletions
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 f90e27d23d8..9daa9c9936a 100644
--- a/addons/web/static/src/js/views/basic/basic_renderer.js
+++ b/addons/web/static/src/js/views/basic/basic_renderer.js
@@ -100,8 +100,10 @@ var BasicRenderer = AbstractRenderer.extend(WidgetAdapterMixin, {
if (!canBeSaved) {
invalidFields.push(widget.name);
}
- widget.$el.toggleClass('o_field_invalid', !canBeSaved);
- widget.$el.attr('aria-invalid', !canBeSaved);
+ if (widget.el) { // widget may not be started yet
+ widget.$el.toggleClass('o_field_invalid', !canBeSaved);
+ widget.$el.attr('aria-invalid', !canBeSaved);
+ }
});
return invalidFields;
},
diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js
index 56fba6515bc..99c49fc9519 100644
--- a/addons/web/static/tests/views/form_tests.js
+++ b/addons/web/static/tests/views/form_tests.js
@@ -1434,6 +1434,64 @@ QUnit.module('Views', {
form.destroy();
});
+ QUnit.test('button in form view and long willStart', async function (assert) {
+ assert.expect(6);
+
+ var rpcCount = 0;
+
+ var FieldChar = fieldRegistry.get('char');
+ fieldRegistry.add('asyncwidget', FieldChar.extend({
+ willStart: function () {
+ assert.step('load '+rpcCount);
+ if (rpcCount === 2) {
+ return $.Deferred();
+ }
+ return $.Deferred().resolve();
+ },
+ }));
+
+ var form = await createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<field name="state" invisible="1"/>' +
+ '<header>' +
+ '<button name="post" class="p" string="Confirm" type="object"/>' +
+ '</header>' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="foo" widget="asyncwidget"/>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 2,
+ mockRPC: function () {
+ rpcCount++;
+ return this._super.apply(this, arguments);
+ },
+ });
+ assert.verifySteps(['load 1']);
+
+ await testUtils.mock.intercept(form, 'execute_action', function (ev) {
+ ev.data.on_success();
+ ev.data.on_closed();
+ });
+
+ await testUtils.dom.click('.o_form_statusbar button.p', form);
+ assert.verifySteps(['load 2']);
+
+ testUtils.mock.intercept(form, 'execute_action', function (ev) {
+ ev.data.on_success();
+ ev.data.on_closed();
+ });
+
+ await testUtils.dom.click('.o_form_statusbar button.p', form);
+ assert.verifySteps(['load 3']);
+
+ form.destroy();
+ });
+
QUnit.test('buttons in form view, new record', async function (assert) {
// this simulates a situation similar to the settings forms.
assert.expect(7);