[FIX] web: switch the record with keynav in FormView

Before this commit, in a formView, if you modify an input and use
the keynav (alt+n or alt+p) to change the record, then the modification
is not saved.

How to reproduce?
- go to a form view with a pager containing more than one record
- edit an input
- press alt+n to move to the next record
- press alt+p to go back to the previous record

Result before:
    The record has not changed

Result after:
    The record has saved the change.

closes odoo/odoo#98602

Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
FrancoisGe
2022-08-23 16:29:25 +02:00
parent fff7334d09
commit 4f87c9c07f
4 changed files with 77 additions and 4 deletions
@@ -113,6 +113,9 @@ export function useInputField(params) {
});
useBus(env.bus, "RELATIONAL_MODEL:WILL_SAVE_URGENTLY", () => commitChanges(true));
useBus(env.bus, "RELATIONAL_MODEL:NEED_LOCAL_CHANGES", (ev) =>
ev.detail.proms.push(commitChanges())
);
/**
* Roughly the same as onChange, but called at more specific / critical times. (See bus events)
@@ -185,9 +185,7 @@ export class FormController extends Component {
limit: 1,
total: resIds.length,
onUpdate: async ({ offset }) => {
if (this.model.root.isDirty) {
await this.model.root.save({ stayInEdition: true });
}
await this.model.root.save({ stayInEdition: true });
this.model.load({ resId: resIds[offset] });
},
};
@@ -1239,7 +1239,6 @@ export class Record extends DataPoint {
* @returns {Promise<boolean>}
*/
async _save(options = { stayInEdition: false, noReload: false }) {
this.model.env.bus.trigger("RELATIONAL_MODEL:NEED_LOCAL_CHANGES");
if (!(await this._checkValidity())) {
const invalidFields = [...this._invalidFields].map((fieldName) => {
return `<li>${escape(this.fields[fieldName].string || fieldName)}</li>`;
@@ -18,6 +18,7 @@ import {
patchWithCleanup,
selectDropdownItem,
triggerEvent,
triggerHotkey,
} from "@web/../tests/helpers/utils";
import { FieldOne2Many } from "web.relational_fields";
import { FieldChar as LegacyFieldChar } from "web.basic_fields";
@@ -4254,6 +4255,78 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(nbWrite, 1, "one write RPC should have been done");
});
QUnit.test("keynav switching to another record from a dirty one", async function (assert) {
let nbWrite = 0;
await makeView({
type: "form",
resModel: "partner",
serverData,
arch: '<form><field name="foo"></field></form>',
resIds: [1, 2],
resId: 1,
mockRPC(route) {
if (route === "/web/dataset/call_kw/partner/write") {
nbWrite++;
}
},
});
assert.strictEqual(
target.querySelector(".o_pager_value").textContent,
"1",
"pager value should be 1"
);
assert.strictEqual(
target.querySelector(".o_pager_limit").textContent,
"2",
"pager limit should be 2"
);
// switch to edit mode
await click(target.querySelector(".o_form_button_edit"));
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"yop",
"input should contain yop"
);
// edit the foo field
const input = target.querySelector(".o_field_widget[name=foo] input");
input.value = "new value";
await triggerEvent(input, null, "input");
// click on the pager to switch to the next record (will save record)
triggerHotkey("alt+n");
await nextTick();
assert.containsNone(document.body, ".modal", "no confirm modal should be displayed");
assert.strictEqual(
target.querySelector(".o_pager_value").textContent,
"2",
"pager value should be 2"
);
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"blip",
"input should contain blip"
);
triggerHotkey("alt+p");
await nextTick();
assert.containsNone(document.body, ".modal", "no confirm modal should be displayed");
assert.strictEqual(
target.querySelector(".o_pager_value").textContent,
"1",
"pager value should be 1"
);
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"new value",
"input should contain new value"
);
assert.strictEqual(nbWrite, 1, "one write RPC should have been done");
});
QUnit.test("handling dirty state: switching to another record", async function (assert) {
await makeView({
type: "form",