[FIX] web: click on ViewButton will close parent Dropdown
# Issue A Dropdown is not closed when a child ViewButton is clicked. # Solution Make the ViewButton close the Dropdown. # Note Usually, a dropdown is closed by a DropdownItem component. This is not the case here, because the clicks on view buttons are stopped (see the view button template). Letting them bubble would close their eventual parent dropdown, but it brings other issues (e.g. for a view button in a list renderer's group row, or view buttons that could get interpreted as action links under some conditions <a type="action" .../>). Instead of looking in the env to close the parent dropdown if any, an alternative solution would be to extend the ViewButton component, wrap it in a DropdownItem component, and reroute its `onClick` handler to the DropdownItem's `onSelected` prop. But this requires some preparation at the form compiler level (when compiling the status bar buttons), which we thought was overengineering at the time of writing. closes odoo/odoo#98399 Signed-off-by: Samuel Degueldre <sad@odoo.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { DROPDOWN } from "@web/core/dropdown/dropdown";
|
||||
import { debounce as debounceFn } from "@web/core/utils/timing";
|
||||
|
||||
const { Component } = owl;
|
||||
@@ -84,6 +85,11 @@ export class ViewButton extends Component {
|
||||
this.env.onClickViewButton({
|
||||
clickParams: this.clickParams,
|
||||
record: this.props.record,
|
||||
beforeExecute: () => {
|
||||
if (this.env[DROPDOWN]) {
|
||||
this.env[DROPDOWN].close();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
/** @odoo-module */
|
||||
import { ViewButton } from "@web/views/view_button/view_button";
|
||||
import { useViewButtons } from "@web/views/view_button/view_button_hook";
|
||||
import { setupViewRegistries } from "./helpers";
|
||||
import { click, getFixture } from "../helpers/utils";
|
||||
import { click, getFixture, mount } from "../helpers/utils";
|
||||
import { makeTestEnv } from "../helpers/mock_env";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { Dropdown } from "@web/core/dropdown/dropdown";
|
||||
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
|
||||
|
||||
const { useRef, mount, Component, xml } = owl;
|
||||
const { useRef, Component, xml } = owl;
|
||||
|
||||
QUnit.module("UseViewButton tests", (hooks) => {
|
||||
let target;
|
||||
@@ -76,4 +79,48 @@ QUnit.module("UseViewButton tests", (hooks) => {
|
||||
await click(target, ".myComponent");
|
||||
assert.verifySteps(["beforeExecuteAction on handler"]);
|
||||
});
|
||||
|
||||
QUnit.test("ViewButton clicked in Dropdown close the Dropdown", async (assert) => {
|
||||
registry.category("services").add(
|
||||
"action",
|
||||
{
|
||||
start() {
|
||||
return {
|
||||
doActionButton() {
|
||||
assert.step("doActionButton");
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{ force: true }
|
||||
);
|
||||
|
||||
class MyComponent extends Component {
|
||||
setup() {
|
||||
const rootRef = useRef("root");
|
||||
useViewButtons({}, rootRef);
|
||||
}
|
||||
}
|
||||
MyComponent.components = { Dropdown, DropdownItem, ViewButton };
|
||||
MyComponent.template = xml`
|
||||
<div t-ref="root" class="myComponent">
|
||||
<Dropdown>
|
||||
<t t-set-slot="toggler">dropdown</t>
|
||||
<DropdownItem>
|
||||
<ViewButton tag="'a'" clickParams="{ type:'action' }" string="'coucou'" record="{ resId: 1 }" />
|
||||
</DropdownItem>
|
||||
</Dropdown>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const env = await makeTestEnv();
|
||||
await mount(MyComponent, target, { env });
|
||||
|
||||
await click(target, ".dropdown-toggle");
|
||||
assert.containsOnce(target, ".dropdown-menu");
|
||||
|
||||
await click(target, "a[type=action]");
|
||||
assert.verifySteps(["doActionButton"]);
|
||||
assert.containsNone(target, ".dropdown-menu");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user