mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] hooks: reintroduce useExternalListener
This commit is contained in:
committed by
Géry Debongnie
parent
3ceb118ace
commit
6ae92fa4b3
@@ -90,3 +90,32 @@ export function useEffect(effect: Effect, computeDependencies: () => any[] = ()
|
|||||||
|
|
||||||
onWillUnmount(() => cleanup());
|
onWillUnmount(() => cleanup());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// useExternalListener
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a component needs to listen to DOM Events on element(s) that are not
|
||||||
|
* part of his hierarchy, we can use the `useExternalListener` hook.
|
||||||
|
* It will correctly add and remove the event listener, whenever the
|
||||||
|
* component is mounted and unmounted.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* a menu needs to listen to the click on window to be closed automatically
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* in the constructor of the OWL component that needs to be notified,
|
||||||
|
* `useExternalListener(window, 'click', this._doSomething);`
|
||||||
|
* */
|
||||||
|
export function useExternalListener(
|
||||||
|
target: HTMLElement | typeof window,
|
||||||
|
eventName: string,
|
||||||
|
handler: EventListener,
|
||||||
|
eventParams?: AddEventListenerOptions
|
||||||
|
) {
|
||||||
|
const node = getCurrent()!;
|
||||||
|
const boundHandler = handler.bind(node.component);
|
||||||
|
onMounted(() => target.addEventListener(eventName, boundHandler, eventParams));
|
||||||
|
onWillUnmount(() => target.removeEventListener(eventName, boundHandler, eventParams));
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ export { Portal } from "./misc/portal";
|
|||||||
export { Memo } from "./misc/memo";
|
export { Memo } from "./misc/memo";
|
||||||
export { css, xml } from "./tags";
|
export { css, xml } from "./tags";
|
||||||
export { useState } from "./reactivity";
|
export { useState } from "./reactivity";
|
||||||
export { useRef, useEnv, useSubEnv, useEffect } from "./hooks";
|
export { useEffect, useEnv, useExternalListener, useRef, useSubEnv } from "./hooks";
|
||||||
export const utils = { EventBus, whenReady, loadFile };
|
export const utils = { EventBus, whenReady, loadFile };
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
@@ -212,6 +212,37 @@ exports[`hooks useEffect hook effect with empty dependency list never reruns 1`]
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`hooks useExternalListener 1`] = `
|
||||||
|
"function anonymous(bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||||
|
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<span><block-text-0/></span>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let d1 = ctx['props'].value;
|
||||||
|
return block1([d1]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`hooks useExternalListener 2`] = `
|
||||||
|
"function anonymous(bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, component } = bdom;
|
||||||
|
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let b2;
|
||||||
|
if (ctx['state'].flag) {
|
||||||
|
b2 = component(\`MyComponent\`, {}, key + \`__1\`, node, ctx);
|
||||||
|
}
|
||||||
|
return multi([b2]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`hooks useRef hook: basic use 1`] = `
|
exports[`hooks useRef hook: basic use 1`] = `
|
||||||
"function anonymous(bdom, helpers
|
"function anonymous(bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -2,19 +2,20 @@ import {
|
|||||||
App,
|
App,
|
||||||
Component,
|
Component,
|
||||||
mount,
|
mount,
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
useComponent,
|
|
||||||
useEnv,
|
|
||||||
useSubEnv,
|
|
||||||
useEffect,
|
|
||||||
onMounted,
|
onMounted,
|
||||||
onPatched,
|
onPatched,
|
||||||
onWillStart,
|
|
||||||
onWillUpdateProps,
|
|
||||||
onWillPatch,
|
onWillPatch,
|
||||||
xml,
|
onWillStart,
|
||||||
onWillUnmount,
|
onWillUnmount,
|
||||||
|
onWillUpdateProps,
|
||||||
|
useComponent,
|
||||||
|
useEffect,
|
||||||
|
useEnv,
|
||||||
|
useExternalListener,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
useSubEnv,
|
||||||
|
xml,
|
||||||
} from "../../src/index";
|
} from "../../src/index";
|
||||||
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
|
||||||
|
|
||||||
@@ -287,13 +288,13 @@ describe("hooks", () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.skip("useExternalListener", async () => {
|
test("useExternalListener", async () => {
|
||||||
let n = 0;
|
let n = 0;
|
||||||
|
|
||||||
class MyComponent extends Component {
|
class MyComponent extends Component {
|
||||||
static template = xml`<span><t t-esc="props.value"/></span>`;
|
static template = xml`<span><t t-esc="props.value"/></span>`;
|
||||||
setup() {
|
setup() {
|
||||||
//useExternalListener(window as any, "click", this.increment);
|
useExternalListener(window, "click", this.increment);
|
||||||
}
|
}
|
||||||
increment() {
|
increment() {
|
||||||
n++;
|
n++;
|
||||||
|
|||||||
Reference in New Issue
Block a user