diff --git a/addons/web/static/src/js/views/basic/widget_wrapper.js b/addons/web/static/src/js/views/basic/widget_wrapper.js index cbc795a1a3f..de11ee5873d 100644 --- a/addons/web/static/src/js/views/basic/widget_wrapper.js +++ b/addons/web/static/src/js/views/basic/widget_wrapper.js @@ -9,10 +9,15 @@ odoo.define('web.WidgetWrapper', function (require) { // Public //---------------------------------------------------------------------- + /** + * This function should be used to update the "widget" Component's props, + * not its state! + * + * @param {any} state + * @returns Promise + */ updateState(state) { - if (this.componentRef.comp.updateState) { - this.componentRef.comp.updateState(state); - } + return this.update(Object.assign({}, this.props, { record: state })); } } return WidgetWrapper; diff --git a/addons/web/static/src/js/widgets/week_days.js b/addons/web/static/src/js/widgets/week_days.js index 0ba69c9227f..0c014b438e4 100644 --- a/addons/web/static/src/js/widgets/week_days.js +++ b/addons/web/static/src/js/widgets/week_days.js @@ -19,9 +19,12 @@ odoo.define('web.WeekDays', function (require) { /** * @override + * @param {Object} nextProps + * @param {Object} nextProps.record */ - updateState(state) { - this.state.days = this._prepareData(state.data); + async willUpdateProps(nextProps) { + this.state.days = this._prepareData(nextProps.record.data); + this.mode = nextProps.options.mode; } //-------------------------------------------------------------------------- diff --git a/addons/web/static/tests/owl_compatibility_tests.js b/addons/web/static/tests/owl_compatibility_tests.js index 7be3b17b857..e5b8e937c8c 100644 --- a/addons/web/static/tests/owl_compatibility_tests.js +++ b/addons/web/static/tests/owl_compatibility_tests.js @@ -1,6 +1,11 @@ odoo.define('web.OwlCompatibilityTests', function (require) { "use strict"; + const AbstractField = require('web.AbstractField'); + const fieldRegistry = require('web.field_registry'); + const widgetRegistry = require('web.widgetRegistry'); + const FormView = require('web.FormView'); + const { ComponentAdapter, ComponentWrapper, WidgetAdapterMixin } = require('web.OwlCompatibility'); const testUtils = require('web.test_utils'); const Widget = require('web.Widget'); @@ -1301,5 +1306,64 @@ odoo.define('web.OwlCompatibilityTests', function (require) { parent.destroy(); }); + + QUnit.module("WidgetWrapper"); + + QUnit.test("correctly update widget component during mounting", async function (assert) { + // It comes with a fix for a bug that occurred because in some circonstances, + // a widget component can be updated twice. + // Specifically, this occurs when there is 'pad' widget in the form view, because this + // widget does a 'setValue' in its 'renderEdit', which thus resets the widget component. + assert.expect(4); + + const PadLikeWidget = fieldRegistry.get('char').extend({ + _renderEdit() { + assert.step("setValue"); + this._setValue("some value"); + } + }); + fieldRegistry.add('pad_like', PadLikeWidget); + + class WidgetComponent extends Component {} + WidgetComponent.template = xml`
Widget
`; + widgetRegistry.add("widget_comp", WidgetComponent); + + const form = await testUtils.createView({ + View: FormView, + model: 'partner', + res_id: 1, + data: { + partner: { + fields: { + id: {string: "id", type:"integer"}, + foo: {string: "Foo", type: "char"}, + }, + records: [{ + id: 1, + foo: "value", + }], + }, + }, + arch: ` +
+ + +
+ `, + }); + + assert.containsOnce(form, ".o_form_view.o_form_readonly"); + + await testUtils.dom.click(form.$(".o_form_label")[0]); + await testUtils.nextTick(); // wait for quick edit + + assert.containsOnce(form, ".o_form_view.o_form_editable"); + assert.verifySteps(["setValue"]); + + form.destroy(); + + delete fieldRegistry.map.pad_like; + delete widgetRegistry.map.widget_comp; + }); }); });