Skip to content

Commit f9ec272

Browse files
committed
[FIX] web: onchange warning from within a formViewDialog
Have a model that returns a warning onchange during the first call to onchange. On another model that has a many2one to the first model, Create And Edit a record via the many2one field on the form view. Before this commit, there was an endless loop because on dialog was triggering the opening of a second one *during* its willStart lifecycle period, so none of them end up mounted, instead, the formViewDialog was constantly reinstanciated because the dialog container constantly received requests to re-render. After this commit, we only open those dialog onMounted of the main component, and this issue doesn't occur anymore. opw-4783459 closes odoo#213742 Signed-off-by: Aaron Bohy (aab) <[email protected]>
1 parent 45dee9a commit f9ec272

File tree

3 files changed

+69
-6
lines changed

3 files changed

+69
-6
lines changed

addons/web/static/src/views/model.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { SEARCH_KEYS } from "@web/search/with_search/with_search";
55
import { buildSampleORM } from "@web/views/sample_server";
66
import { useSetupView } from "@web/views/view_hook";
77

8-
import { EventBus, onWillStart, onWillUpdateProps, status, useComponent } from "@odoo/owl";
8+
import { EventBus, onMounted, onWillStart, onWillUpdateProps, status, useComponent } from "@odoo/owl";
99

1010
/**
1111
* @typedef {import("@web/search/search_model").SearchParams} SearchParams
@@ -94,6 +94,26 @@ export function useModel(ModelClass, params, options = {}) {
9494
services[key] = useService(key);
9595
}
9696
services.orm = services.orm || useService("orm");
97+
if (services.dialog) {
98+
services.dialog = Object.create(services.dialog);
99+
const dialogAddOrigin = services.dialog.add;
100+
let dialogRequests = [];
101+
services.dialog.add = (...args) => {
102+
const index = dialogRequests.push(args);
103+
return () => {
104+
dialogRequests[index] = null;
105+
}
106+
}
107+
onMounted(() => {
108+
services.dialog.add = dialogAddOrigin;
109+
for (const req of dialogRequests) {
110+
if (req) {
111+
dialogAddOrigin(...req);
112+
}
113+
}
114+
dialogRequests = null;
115+
});
116+
}
97117

98118
if (!("isAlive" in params)) {
99119
params.isAlive = () => status(component) !== "destroyed";

addons/web/static/tests/views/view_dialogs/form_view_dialog_tests.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
patchWithCleanup,
99
triggerHotkey,
1010
} from "@web/../tests/helpers/utils";
11+
import { contains } from "@web/../tests/utils";
1112
import { makeView } from "@web/../tests/views/helpers";
1213
import { createWebClient } from "@web/../tests/webclient/helpers";
1314
import { FormViewDialog } from "@web/views/view_dialogs/form_view_dialog";
@@ -376,4 +377,49 @@ QUnit.module("ViewDialogs", (hooks) => {
376377
assert.containsNone(target, ".modal", "modal should be closed");
377378
}
378379
);
380+
381+
QUnit.test("display a dialog if onchange result is a warning from within a dialog", async function (assert) {
382+
serverData.views = {
383+
"instrument,false,form": `<form><field name="display_name" /></form>`
384+
};
385+
await makeView({
386+
type: "form",
387+
resModel: "partner",
388+
serverData,
389+
arch: `<form><field name="instrument"/></form>`,
390+
resId: 2,
391+
mockRPC(route, args) {
392+
if (args.method === "onchange" && args.model === "instrument") {
393+
assert.step("onchange warning")
394+
return Promise.resolve({
395+
warning: {
396+
title: "Warning",
397+
message: "You must first select a partner",
398+
type: "dialog",
399+
},
400+
});
401+
}
402+
},
403+
});
404+
405+
await editInput(target, ".o_field_widget[name=instrument] input", "tralala");
406+
await contains(".o_m2o_dropdown_option_create_edit a");
407+
408+
await click(target.querySelector(".o_m2o_dropdown_option_create_edit a"));
409+
await contains(".modal.o_inactive_modal");
410+
assert.containsN(document.body, ".modal", 2);
411+
assert.strictEqual(
412+
document.body.querySelector(".modal:not(.o_inactive_modal) .modal-body").textContent,
413+
"You must first select a partner"
414+
);
415+
416+
await click(document.body.querySelector(".modal:not(.o_inactive_modal) button"))
417+
assert.containsOnce(target, ".modal");
418+
assert.strictEqual(
419+
document.body.querySelector(".modal:not(.o_inactive_modal) .modal-title").textContent,
420+
"Create Instruments"
421+
);
422+
423+
assert.verifySteps(["onchange warning"])
424+
});
379425
});

addons/web/static/tests/webclient/actions/window_action_tests.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
patchWithCleanup,
2121
clickSave,
2222
} from "../../helpers/utils";
23+
import { contains } from "@web/../tests/utils";
2324
import { createWebClient, doAction, getActionManagerServerData, loadState } from "./../helpers";
2425
import { errorService } from "../../../src/core/errors/error_service";
2526
import { RPCError } from "@web/core/network/rpc_service";
@@ -2196,11 +2197,7 @@ QUnit.module("ActionManager", (hooks) => {
21962197
await doAction(webClient, 3);
21972198

21982199
await click(target.querySelector(".o_list_button_add"));
2199-
assert.containsOnce(
2200-
document.body,
2201-
".modal.o_technical_modal",
2202-
"Warning modal should be opened"
2203-
);
2200+
await contains(".modal.o_technical_modal");
22042201

22052202
await click(document.querySelector(".modal.o_technical_modal button.btn-close"));
22062203
assert.containsNone(

0 commit comments

Comments
 (0)