[FIX] web: nested x2manys with context referencing parent
Before this commit, it crashed if an x2many field inside another
x2many field had a context with a key referencing the parent
record:
```xml
<form>
<field name="foo"/>
<field name="outer_x2many">
<tree></tree>
<form>
<field name="inner_x2many" context="{'key': parent.foo}">
<tree></tree>
</field>
</form>
</field>
</form>
```
The crash occured because we tried to evaluate the context of the
static list representing inner_x2many before setting the parent
key on the eval context.
Part of task~3179751
Part-of: odoo/odoo#114024
This commit is contained in:
@@ -37,6 +37,16 @@ export class Record extends DataPoint {
|
||||
this._unsetRequiredFields = markRaw(new Set());
|
||||
this._closeInvalidFieldsNotification = () => {};
|
||||
|
||||
const parentRecord = this._parentRecord;
|
||||
if (parentRecord) {
|
||||
this.evalContext = {
|
||||
get parent() {
|
||||
return parentRecord.evalContext;
|
||||
},
|
||||
};
|
||||
} else {
|
||||
this.evalContext = {};
|
||||
}
|
||||
const missingFields = this.fieldNames.filter((fieldName) => !(fieldName in data));
|
||||
data = { ...this._getDefaultValues(missingFields), ...data };
|
||||
const vals = this._parseServerValues(data);
|
||||
@@ -55,23 +65,12 @@ export class Record extends DataPoint {
|
||||
// expose string values (false fallbacks on the empty string) in this.data.
|
||||
this._textValues = markRaw({});
|
||||
this._setTextValues(data);
|
||||
this._setEvalContext();
|
||||
this._savePoint = markRaw({
|
||||
dirty: false,
|
||||
changes: { ...this._changes },
|
||||
textValues: { ...this._textValues },
|
||||
});
|
||||
|
||||
const parentRecord = this._parentRecord;
|
||||
if (parentRecord) {
|
||||
this.evalContext = {
|
||||
get parent() {
|
||||
return parentRecord.evalContext;
|
||||
},
|
||||
};
|
||||
} else {
|
||||
this.evalContext = {};
|
||||
}
|
||||
this._setEvalContext();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@@ -7661,6 +7661,50 @@ QUnit.module("Fields", (hooks) => {
|
||||
await click(target.querySelector(".o_field_x2many_list_row_add a"));
|
||||
});
|
||||
|
||||
QUnit.test("nested x2manys with context referencing parent record", async function (assert) {
|
||||
assert.expect(3);
|
||||
|
||||
serverData.models.partner.records[0].p = [2];
|
||||
|
||||
let onchangeNb = 0;
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
serverData,
|
||||
arch: `
|
||||
<form>
|
||||
<field name="foo"/>
|
||||
<field name="p">
|
||||
<tree>
|
||||
<field name="display_name"/>
|
||||
</tree>
|
||||
<form>
|
||||
<field name="p" context="{'parent_foo': parent.foo}">
|
||||
<tree>
|
||||
<field name="display_name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</form>
|
||||
</field>
|
||||
</form>`,
|
||||
mockRPC(route, args) {
|
||||
if (args.method === "onchange2") {
|
||||
onchangeNb++;
|
||||
if (onchangeNb === 1) {
|
||||
assert.deepEqual(args.args[3].p.context, { parent_foo: "yop" });
|
||||
} else {
|
||||
assert.strictEqual(args.kwargs.context.parent_foo, "yop");
|
||||
}
|
||||
}
|
||||
},
|
||||
resId: 1,
|
||||
});
|
||||
|
||||
await click(target.querySelector(".o_field_x2many_list_row_add a"));
|
||||
assert.containsOnce(target, ".o_dialog");
|
||||
await click(target.querySelector(".o_dialog .o_field_x2many_list_row_add a"));
|
||||
});
|
||||
|
||||
QUnit.test("resetting invisible one2manys", async function (assert) {
|
||||
serverData.models.partner.records[0].turtles = [];
|
||||
serverData.models.partner.onchanges.foo = function (obj) {
|
||||
|
||||
Reference in New Issue
Block a user