[REF] web: useTooltip: use template instead of component
Allowing to specify components inside tooltips to obtain dynamic and/or html content was a bit overkill and unnecessary: a template can do the trick and it is easier to define. This commit thus renames attribute "data-tooltip-component" into "data-tooltip-template" (the name of the qweb template) and introduces the "data-tooltip-info" attribute (its value is then available in the template under the "info" variable). X-original-commit: 8683a8d762339451e3d9f8706aac86da80510b37 Part-of: odoo/odoo#77113
This commit is contained in:
@@ -5,7 +5,7 @@ const { Component } = owl;
|
||||
export class Tooltip extends Component {}
|
||||
Tooltip.template = "web.Tooltip";
|
||||
Tooltip.props = {
|
||||
tooltip: String,
|
||||
Component: { optional: true },
|
||||
props: { optional: true },
|
||||
tooltip: { type: String, optional: true },
|
||||
template: { type: String, optional: true },
|
||||
info: { optional: true },
|
||||
};
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
<t t-name="web.Tooltip" owl="1">
|
||||
<div class="o-tooltip px-2 py-1">
|
||||
<t t-if="props.Component" t-component="props.Component" t-props="props.props" />
|
||||
<t t-if="props.template" t-call="{{props.template}}">
|
||||
<t t-set="info" t-value="props.info"/>
|
||||
</t>
|
||||
<small t-else="" t-esc="props.tooltip"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { browser } from "@web/core/browser/browser";
|
||||
import { useListener } from "@web/core/utils/hooks";
|
||||
import { usePopover } from "@web/core/popover/popover_hook";
|
||||
import { Tooltip } from "./tooltip";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
/**
|
||||
* The useTooltip hook allows to display custom tooltips on every elements with
|
||||
@@ -18,6 +17,19 @@ import { registry } from "@web/core/registry";
|
||||
* The ideal position of the tooltip can be specified thanks to the attribute
|
||||
* "data-tooltip-position":
|
||||
* <button data-tooltip="This is a tooltip" data-tooltip-position="left">Do something</button>
|
||||
*
|
||||
* For advanced tooltips containing dynamic and/or html content, the
|
||||
* "data-tooltip-template" and "data-tooltip-info" attributes can be used.
|
||||
* For example, let's suppose the following qweb template:
|
||||
* <t t-name="some_template">
|
||||
* <ul>
|
||||
* <li>info.x</li>
|
||||
* <li>info.y</li>
|
||||
* </ul>
|
||||
* </t>
|
||||
* This template can then be used in a tooltip as follows:
|
||||
* <button data-tooltip-template="some_template" data-tooltip-info="info">Do something</button>
|
||||
* with "info" being a stringified object with two keys "x" and "y".
|
||||
*/
|
||||
const OPEN_DELAY = 400;
|
||||
const CLOSE_DELAY = 200;
|
||||
@@ -46,13 +58,12 @@ export function useTooltip() {
|
||||
function onMouseEnter(ev) {
|
||||
const dataset = ev.target.dataset;
|
||||
const tooltip = dataset.tooltip;
|
||||
|
||||
let Component, props;
|
||||
if ("tooltipComponent" in dataset) {
|
||||
({ Component, props } = JSON.parse(dataset["tooltipComponent"]));
|
||||
Component = registry.category("tooltips").get(Component, null);
|
||||
let template, info;
|
||||
if ("tooltipTemplate" in dataset) {
|
||||
template = dataset.tooltipTemplate;
|
||||
info = dataset.tooltipInfo ? JSON.parse(dataset.tooltipInfo) : null;
|
||||
}
|
||||
if (tooltip || Component) {
|
||||
if (tooltip || template) {
|
||||
cleanup();
|
||||
target = ev.target;
|
||||
openTooltipTimeout = browser.setTimeout(() => {
|
||||
@@ -60,7 +71,7 @@ export function useTooltip() {
|
||||
closeTooltip = popover.add(
|
||||
target,
|
||||
Tooltip,
|
||||
{ tooltip, Component, props },
|
||||
{ tooltip, template, info },
|
||||
{ position }
|
||||
);
|
||||
}, OPEN_DELAY);
|
||||
@@ -97,6 +108,7 @@ export function useTooltip() {
|
||||
}, CLOSE_DELAY);
|
||||
|
||||
// Listen (using event delegation) to "mouseenter" events on all nodes with
|
||||
// the "data-tooltip" attribute, to open the tooltip.
|
||||
useListener("mouseenter", "[data-tooltip]", onMouseEnter, { capture: true });
|
||||
// the "data-tooltip" or "data-tooltip-template" attribute, to open the tooltip.
|
||||
const selector = "[data-tooltip], [data-tooltip-template]";
|
||||
useListener("mouseenter", selector, onMouseEnter, { capture: true });
|
||||
}
|
||||
|
||||
@@ -203,4 +203,53 @@ QUnit.module("Tooltip hook", () => {
|
||||
assert.strictEqual(parent.el.querySelector(".o_popover").innerText, "left");
|
||||
assert.hasClass(parent.el.querySelector(".o_popover"), "o-popper-position--lm");
|
||||
});
|
||||
|
||||
QUnit.test("tooltip with a template, no info", async (assert) => {
|
||||
class MyComponent extends Component {}
|
||||
MyComponent.template = xml`
|
||||
<button data-tooltip-template="my_tooltip_template">Action</button>
|
||||
`;
|
||||
const parent = await makeParent(MyComponent);
|
||||
parent.env.qweb.addTemplate("my_tooltip_template", "<i>tooltip</i>");
|
||||
|
||||
assert.containsNone(parent, ".o_popover_container .o-tooltip");
|
||||
parent.el.querySelector("button").dispatchEvent(new Event("mouseenter"));
|
||||
await nextTick();
|
||||
assert.containsOnce(parent, ".o_popover_container .o-tooltip");
|
||||
assert.strictEqual(parent.el.querySelector(".o-tooltip").innerHTML, "<i>tooltip</i>");
|
||||
});
|
||||
|
||||
QUnit.test("tooltip with a template and info", async (assert) => {
|
||||
class MyComponent extends Component {
|
||||
get info() {
|
||||
return JSON.stringify({ x: 3, y: "abc" });
|
||||
}
|
||||
}
|
||||
MyComponent.template = xml`
|
||||
<button
|
||||
data-tooltip-template="my_tooltip_template"
|
||||
t-att-data-tooltip-info="info">
|
||||
Action
|
||||
</button>
|
||||
`;
|
||||
const parent = await makeParent(MyComponent);
|
||||
parent.env.qweb.addTemplate(
|
||||
"my_tooltip_template",
|
||||
`
|
||||
<ul>
|
||||
<li>X: <t t-esc="info.x"/></li>
|
||||
<li>Y: <t t-esc="info.y"/></li>
|
||||
</ul>
|
||||
`
|
||||
);
|
||||
|
||||
assert.containsNone(parent, ".o_popover_container .o-tooltip");
|
||||
parent.el.querySelector("button").dispatchEvent(new Event("mouseenter"));
|
||||
await nextTick();
|
||||
assert.containsOnce(parent, ".o_popover_container .o-tooltip");
|
||||
assert.strictEqual(
|
||||
parent.el.querySelector(".o-tooltip").innerHTML,
|
||||
"<ul><li>X: 3</li><li>Y: abc</li></ul>"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user