[IMP] hooks: reintroduce useExternalListener

This commit is contained in:
Bruno Boi
2021-11-15 15:05:44 +01:00
committed by Aaron Bohy
parent 81e5b24f2f
commit b2ea241270
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());
}
// -----------------------------------------------------------------------------
// 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 { css, xml } from "./tags";
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 {
@@ -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`] = `
"function anonymous(bdom, helpers
) {
+12 -11
View File
@@ -2,19 +2,20 @@ import {
App,
Component,
mount,
useRef,
useState,
useComponent,
useEnv,
useSubEnv,
useEffect,
onMounted,
onPatched,
onWillStart,
onWillUpdateProps,
onWillPatch,
xml,
onWillStart,
onWillUnmount,
onWillUpdateProps,
useComponent,
useEffect,
useEnv,
useExternalListener,
useRef,
useState,
useSubEnv,
xml,
} from "../../src/index";
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
@@ -287,13 +288,13 @@ describe("hooks", () => {
]);
});
test.skip("useExternalListener", async () => {
test("useExternalListener", async () => {
let n = 0;
class MyComponent extends Component {
static template = xml`<span><t t-esc="props.value"/></span>`;
setup() {
//useExternalListener(window as any, "click", this.increment);
useExternalListener(window, "click", this.increment);
}
increment() {
n++;