[FIX] web: can update one2many with custom field widget
One might design a custom field widget to display/interact with a one2many field. Before this commit, if this field widget triggered a field_changed event to update a related record, it crashed, because the code assumed that there was a view associated with the field. Closes #68276 opw~2468238 closes odoo/odoo#68309 X-original-commit: 3826a2645b94e0f62c719814c4dbe4cc6502e1f2 Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com> Signed-off-by: Aaron Bohy (aab) <aab@odoo.com> Co-authored-by: Aaron Bohy <aab@odoo.com>
This commit is contained in:
committed by
Aaron Bohy
co-authored by
Aaron Bohy
parent
d613f97320
commit
b08afa3475
@@ -2053,7 +2053,9 @@ var BasicModel = AbstractModel.extend({
|
||||
case 'UPDATE':
|
||||
list._changes.push({operation: 'UPDATE', id: command.id});
|
||||
if (command.data) {
|
||||
defs.push(this._applyChange(command.id, command.data, { viewType: view.type }));
|
||||
defs.push(this._applyChange(command.id, command.data, {
|
||||
viewType: view && view.type,
|
||||
}));
|
||||
}
|
||||
break;
|
||||
case 'FORGET':
|
||||
|
||||
@@ -9764,6 +9764,77 @@ QUnit.module('fields', {}, function () {
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('update a one2many from a custom field widget', async function (assert) {
|
||||
// In this test, we define a custom field widget to render/update a one2many
|
||||
// field. For the update part, we ensure that updating primitive fields of a sub
|
||||
// record works. There is no guarantee that updating a relational field on the sub
|
||||
// record would work. Deleting a sub record works as well. However, creating sub
|
||||
// records isn't supported. There are obviously a lot of limitations, but the code
|
||||
// hasn't been designed to support all this. This test simply encodes what can be
|
||||
// done, and this comment explains what can't (and won't be implemented in stable
|
||||
// versions).
|
||||
assert.expect(3);
|
||||
|
||||
this.data.partner.records[0].p = [1, 2];
|
||||
const MyRelationalField = AbstractField.extend({
|
||||
events: {
|
||||
'click .update': '_onUpdate',
|
||||
'click .delete': '_onDelete',
|
||||
},
|
||||
async _render() {
|
||||
const records = await this._rpc({
|
||||
method: 'read',
|
||||
model: 'partner',
|
||||
args: [this.value.res_ids],
|
||||
});
|
||||
this.$el.text(records.map(r => `${r.display_name}/${r.int_field}`).join(', '));
|
||||
this.$el.append($('<button class="update fa fa-edit">'));
|
||||
this.$el.append($('<button class="delete fa fa-trash">'));
|
||||
},
|
||||
_onUpdate() {
|
||||
this._setValue({
|
||||
operation: 'UPDATE',
|
||||
id: this.value.data[0].id,
|
||||
data: {
|
||||
display_name: 'new name',
|
||||
int_field: 44,
|
||||
},
|
||||
});
|
||||
},
|
||||
_onDelete() {
|
||||
this._setValue({
|
||||
operation: 'DELETE',
|
||||
ids: [this.value.data[0].id],
|
||||
});
|
||||
},
|
||||
});
|
||||
fieldRegistry.add('my_relational_field', MyRelationalField);
|
||||
|
||||
const form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: `
|
||||
<form>
|
||||
<field name="p" widget="my_relational_field"/>
|
||||
</form>`,
|
||||
res_id: 1,
|
||||
});
|
||||
|
||||
assert.strictEqual(form.$('.o_field_widget[name=p]').text(), 'first record/10, second record/9');
|
||||
|
||||
await testUtils.dom.click(form.$('button.update'));
|
||||
|
||||
assert.strictEqual(form.$('.o_field_widget[name=p]').text(), 'new name/44, second record/9');
|
||||
|
||||
await testUtils.dom.click(form.$('button.delete'));
|
||||
|
||||
assert.strictEqual(form.$('.o_field_widget[name=p]').text(), 'second record/9');
|
||||
|
||||
form.destroy();
|
||||
delete fieldRegistry.map.my_relational_field;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user