[FIX] web: widget noreset if rerendered for modifier
If we have a many2many_tags widget that is writable then becomes
readonly, we can have in the code this chain of event:
- get list of widgets we need to reset some data for
- apply modifiers
- reset the widgets
but applying modifiers can delete a widget (eg. an editable field that
becomes readonly), so when resetting we could call code on a deleted
widget which caused an error.
For example, if we have an attribute:
`<field widget="many2many_tags" attrs="{'readonly': 'condition'}"/>`
if the field goes from editable to readonly and is affected by an
onchange, we will call `setIDForLabel` on the deleted instance of the
widget which will cause an error.
Added test without fix fails with error:
TypeError: Cannot read property 'attr' of undefined
at Class.setIDForLabel (/web/static/src/js/fields/abstract_field.js:324:35)
because as said, the function is called on the editable widget that is
removed and replaced with readonly widget at that point.
opw-2154471
closes #43137
closes odoo/odoo#43244
X-original-commit: 6f5ca16524be7c5bb45b03e7421154a20edc4cf6
Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
This commit is contained in:
@@ -93,6 +93,7 @@ var BasicRenderer = AbstractRenderer.extend({
|
||||
* that have been reset
|
||||
*/
|
||||
confirmChange: function (state, id, fields, ev) {
|
||||
var self = this;
|
||||
this.state = state;
|
||||
var record = this._getRecord(id);
|
||||
if (!record) {
|
||||
@@ -106,12 +107,10 @@ var BasicRenderer = AbstractRenderer.extend({
|
||||
|
||||
// Reset all the field widgets that are marked as changed and the ones
|
||||
// which are configured to always be reset on any change
|
||||
var resetWidgets = [];
|
||||
_.each(this.allFieldWidgets[id], function (widget) {
|
||||
var fieldChanged = _.contains(fields, widget.name);
|
||||
if (fieldChanged || widget.resetOnAnyFieldChange) {
|
||||
defs.push(widget.reset(record, ev, fieldChanged));
|
||||
resetWidgets.push(widget);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -121,7 +120,10 @@ var BasicRenderer = AbstractRenderer.extend({
|
||||
defs.push(this._updateAllModifiers(record));
|
||||
|
||||
return Promise.all(defs).then(function () {
|
||||
return resetWidgets;
|
||||
return _.filter(self.allFieldWidgets[id], function (widget) {
|
||||
var fieldChanged = _.contains(fields, widget.name);
|
||||
return fieldChanged || widget.resetOnAnyFieldChange;
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -4838,6 +4838,33 @@ QUnit.module('Views', {
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('readonly set by modifier do not break many2many_tags', async function (assert) {
|
||||
assert.expect(0);
|
||||
|
||||
this.data.partner.onchanges = {
|
||||
bar: function (obj) {
|
||||
obj.timmy = [[6, false, [12]]];
|
||||
},
|
||||
};
|
||||
var form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<form string="Partners">' +
|
||||
'<sheet>' +
|
||||
'<field name="bar"/>' +
|
||||
'<field name="timmy" widget="many2many_tags" attrs="{\'readonly\': [(\'bar\',\'=\',True)]}"/>' +
|
||||
'</sheet>' +
|
||||
'</form>',
|
||||
res_id: 5,
|
||||
});
|
||||
|
||||
await testUtils.form.clickEdit(form);
|
||||
await testUtils.dom.click(form.$('.o_field_widget[name=bar] input'));
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('check if id and active_id are defined', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user