[IMP] hooks: reintroduce useExternalListener

This commit is contained in:
Bruno Boi
2021-11-15 15:05:44 +01:00
committed by Géry Debongnie
parent 3ceb118ace
commit 6ae92fa4b3
4 changed files with 73 additions and 12 deletions
+29
View File
@@ -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
View File
@@ -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
) { ) {
+12 -11
View File
@@ -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++;