[IMP] web: add a onRecordChanged prop to the Record component
Before this commit, there was no way to instanciate a Record component and be able to handle changes occuring in that record. After this commit, a simple props is added, making this use case possible. closes odoo/odoo#109846 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
@@ -5,21 +5,17 @@ import { useModel } from "@web/views/model";
|
||||
import { RelationalModel } from "@web/views/relational_model";
|
||||
import { Component, xml, onWillStart, onWillUpdateProps } from "@odoo/owl";
|
||||
|
||||
const defaultActiveField = { attrs: {}, options: {}, domain: "[]", string: "" };
|
||||
|
||||
class _Record extends Component {
|
||||
setup() {
|
||||
const activeFields =
|
||||
this.props.info.activeFields ||
|
||||
Object.fromEntries(
|
||||
this.props.info.fieldNames.map((f) => [f, { attrs: {}, options: {}, domain: "[]" }])
|
||||
);
|
||||
|
||||
this.model = useModel(RelationalModel, {
|
||||
resId: this.props.info.resId,
|
||||
resModel: this.props.info.resModel,
|
||||
fields: this.props.fields,
|
||||
viewMode: "form",
|
||||
rootType: "record",
|
||||
activeFields,
|
||||
activeFields: this.getActiveFields(),
|
||||
mode: this.props.info.mode === "edit" ? "edit" : undefined,
|
||||
initialValues: this.props.info.initialValues,
|
||||
});
|
||||
@@ -29,9 +25,36 @@ class _Record extends Component {
|
||||
mode: nextProps.info.mode,
|
||||
});
|
||||
});
|
||||
|
||||
if (this.props.info.onRecordChanged) {
|
||||
const load = this.model.load;
|
||||
this.model.load = async (...args) => {
|
||||
const res = await load.call(this.model, ...args);
|
||||
const root = this.model.root;
|
||||
root.onChanges = async () => {
|
||||
const changes = root.getChanges();
|
||||
this.props.info.onRecordChanged(root, changes);
|
||||
};
|
||||
return res;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getActiveFields() {
|
||||
if (this.props.info.activeFields) {
|
||||
const activeFields = {};
|
||||
for (const [fName, fInfo] of Object.entries(this.props.info.activeFields)) {
|
||||
activeFields[fName] = { ...defaultActiveField, ...fInfo };
|
||||
}
|
||||
return activeFields;
|
||||
}
|
||||
return Object.fromEntries(
|
||||
this.props.info.fieldNames.map((f) => [f, { ...defaultActiveField }])
|
||||
);
|
||||
}
|
||||
}
|
||||
_Record.template = xml`<t t-slot="default" record="model.root"/>`;
|
||||
_Record.props = ["slots", "info", "fields"];
|
||||
|
||||
export class Record extends Component {
|
||||
setup() {
|
||||
@@ -61,4 +84,5 @@ Record.props = [
|
||||
"resId?",
|
||||
"mode?",
|
||||
"initialValues?",
|
||||
"onRecordChanged?",
|
||||
];
|
||||
|
||||
@@ -7,6 +7,7 @@ import { click, getFixture, mount } from "../helpers/utils";
|
||||
import { setupViewRegistries } from "../views/helpers";
|
||||
|
||||
import { Component, xml, useState } from "@odoo/owl";
|
||||
import { editInput } from "@web/../tests/helpers/utils";
|
||||
|
||||
let serverData;
|
||||
let target;
|
||||
@@ -183,4 +184,50 @@ QUnit.module("Record Component", (hooks) => {
|
||||
assert.verifySteps([]);
|
||||
assert.strictEqual(target.querySelector(".o_field_widget input").value, "abc");
|
||||
});
|
||||
|
||||
QUnit.test("provides a way to handle changes in the record", async function (assert) {
|
||||
class Parent extends Component {
|
||||
setup() {
|
||||
this.fields = {
|
||||
foo: {
|
||||
name: "foo",
|
||||
type: "char",
|
||||
},
|
||||
bar: {
|
||||
name: "bar",
|
||||
type: "boolean",
|
||||
},
|
||||
};
|
||||
this.values = {
|
||||
foo: "abc",
|
||||
bar: true,
|
||||
};
|
||||
}
|
||||
|
||||
onRecordChanged(record, changes) {
|
||||
assert.step("record changed");
|
||||
assert.strictEqual(record.model.constructor.name, "RelationalModel");
|
||||
assert.deepEqual(changes, { foo: "753" });
|
||||
}
|
||||
}
|
||||
Parent.components = { Record, Field };
|
||||
Parent.template = xml`
|
||||
<Record resModel="'partner'" fieldNames="['foo']" fields="fields" initialValues="values" t-slot-scope="data" onRecordChanged.bind="onRecordChanged">
|
||||
<Field name="'foo'" record="data.record"/>
|
||||
</Record>
|
||||
`;
|
||||
|
||||
await mount(Parent, target, {
|
||||
env: await makeTestEnv({
|
||||
serverData,
|
||||
mockRPC(route) {
|
||||
assert.step(route);
|
||||
},
|
||||
}),
|
||||
});
|
||||
assert.strictEqual(target.querySelector("[name='foo'] input").value, "abc");
|
||||
await editInput(target, "[name='foo'] input", "753");
|
||||
assert.verifySteps(["record changed"]);
|
||||
assert.strictEqual(target.querySelector("[name='foo'] input").value, "753");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user