diff --git a/addons/web/static/src/legacy/js/fields/signature.js b/addons/web/static/src/legacy/js/fields/signature.js index eadef64d4f5..fea26660a8c 100644 --- a/addons/web/static/src/legacy/js/fields/signature.js +++ b/addons/web/static/src/legacy/js/fields/signature.js @@ -45,10 +45,7 @@ var FieldBinarySignature = AbstractFieldBinary.extend({ * @override */ isSet: function () { - if (this.mode === 'edit') { - return this.value; - } - return true; + return this.value; }, //-------------------------------------------------------------------------- diff --git a/addons/web/static/src/legacy/js/views/form/form_renderer.js b/addons/web/static/src/legacy/js/views/form/form_renderer.js index 3608efe53b6..4c4a517f84c 100644 --- a/addons/web/static/src/legacy/js/views/form/form_renderer.js +++ b/addons/web/static/src/legacy/js/views/form/form_renderer.js @@ -46,6 +46,7 @@ var FormRenderer = BasicRenderer.extend({ this.idsForLabels = {}; this.lastActivatedFieldIndex = -1; this.alertFields = {}; + this.labelsToPostProcess = []; // The form renderer doesn't render invsible fields (invisible="1") by // default, to speed up the rendering. However, we sometimes have to // display them (e.g. in Studio, in "show invisible" mode). This flag @@ -170,6 +171,7 @@ var FormRenderer = BasicRenderer.extend({ if (self.$('.o_field_invalid').length) { self.canBeSaved(self.state.id); } + self._postProcessLabels(); return resetWidgets; }); }, @@ -461,6 +463,18 @@ var FormRenderer = BasicRenderer.extend({ this.defaultFocusField = widget; } }, + /** + * This function is called once form view is rendered or modifiers are + * changed to process labels to add o_form_label_empty. + * + * @private + */ + _postProcessLabels() { + this.labelsToPostProcess.forEach((label) => { + label.call(); + }); + this.labelsToPostProcess = []; + }, /** * @private * @param {Object} node @@ -959,11 +973,12 @@ var FormRenderer = BasicRenderer.extend({ callback: function (element, modifiers, record) { var widgets = self.allFieldWidgets[record.id]; var widget = _.findWhere(widgets, {name: fieldName}); + const fieldsInfo = record.fieldsInfo[self.viewType]; if (!widget) { - return; // FIXME this occurs if the widget is created - // after the label (explicit tag in the - // arch), so this won't work on first rendering - // only on reevaluation + if (fieldsInfo[fieldName]) { + self.labelsToPostProcess.push(element.callback.bind(self, element, modifiers, record)); + } + return; } element.$el.toggleClass('o_form_label_empty', !!( // FIXME condition is evaluated twice (label AND widget...) record.data.id @@ -1090,6 +1105,7 @@ var FormRenderer = BasicRenderer.extend({ delete this.defs; return Promise.all(defs).then(() => this.__renderView()).then(function () { + self._postProcessLabels(); self._updateView($form.contents()); if (self.state.res_id in self.alertFields) { self.displayTranslationAlert(); diff --git a/addons/web/static/tests/legacy/views/form_tests.js b/addons/web/static/tests/legacy/views/form_tests.js index 395b290b4c3..df4d8c00808 100644 --- a/addons/web/static/tests/legacy/views/form_tests.js +++ b/addons/web/static/tests/legacy/views/form_tests.js @@ -1543,6 +1543,65 @@ QUnit.module('Views', { form.destroy(); }); + QUnit.test('label tag added for fields have o_form_empty class in readonly mode if field is empty', async function (assert) { + assert.expect(8); + + this.data.partner.fields.foo.default = false; // no default value for this test + this.data.partner.records[1].foo = false; // 1 is record with id=2 + this.data.partner.records[1].trululu = false; // 1 is record with id=2 + this.data.partner.fields.int_field.readonly = true; + this.data.partner.onchanges.foo = function (obj) { + if (obj.foo === "hello") { + obj.int_field = false; + } + }; + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: `
`, + res_id: 2, + }); + + assert.containsN(form, '.o_field_widget.o_field_empty', 2, + "should have 2 empty fields with correct class"); + assert.containsN(form, '.o_form_label_empty', 2, + "should have 2 muted labels (for the empty fieds) in readonly"); + + await testUtils.form.clickEdit(form); + + assert.containsOnce(form, '.o_field_empty', + "in edit mode, only empty readonly fields should have the o_field_empty class"); + assert.containsOnce(form, '.o_form_label_empty', + "in edit mode, only labels associated to empty readonly fields should have the o_form_label_empty class"); + + await testUtils.fields.editInput(form.$('input[name=foo]'), 'test'); + + assert.containsNone(form, '.o_field_empty', + "after readonly modifier change, the o_field_empty class should have been removed"); + assert.containsNone(form, '.o_form_label_empty', + "after readonly modifier change, the o_form_label_empty class should have been removed"); + + await testUtils.fields.editInput(form.$('input[name=foo]'), 'hello'); + + assert.containsOnce(form, '.o_field_empty', + "after value changed to false for a readonly field, the o_field_empty class should have been added"); + assert.containsOnce(form, '.o_form_label_empty', + "after value changed to false for a readonly field, the o_form_label_empty class should have been added"); + + form.destroy(); + }); + QUnit.test('form view can switch to edit mode', async function (assert) { assert.expect(9);