[ADD] misc: component Portal

The component Portal is used to teleport the content
in its slot as a child of an element
somewhere else in the DOM, usually 'body'

It is designed to be transparent and is just here to do the teleportation task

OwlEvents (with method `Component.trigger`) are redirected from
any Component instanciated within the Portal (and therefore teleported
somewhere else) to the place it would have been without teleportation
i.e. they are re-triggered onto the Portal root node

Co-authored-by: Aaron Bohy <aab@odoo.com>

closes #184
closes #466
This commit is contained in:
Lucas Perais (lpe)
2019-11-15 13:24:07 +01:00
committed by Géry Debongnie
parent 821bd0b4b8
commit 556a4644f0
8 changed files with 1245 additions and 25 deletions
+21 -9
View File
@@ -84,6 +84,8 @@ interface Internal<T extends Env, Props> {
refs: { [key: string]: Component<T, any> | HTMLElement | undefined } | null;
}
export const portalSymbol = Symbol("portal"); // FIXME
//------------------------------------------------------------------------------
// Component
//------------------------------------------------------------------------------
@@ -397,14 +399,7 @@ export class Component<T extends Env, Props extends {}> {
* willUnmount().
*/
trigger(eventType: string, payload?: any) {
if (this.el) {
const ev = new OwlEvent(this, eventType, {
bubbles: true,
cancelable: true,
detail: payload
});
this.el.dispatchEvent(ev);
}
this.__trigger(this, eventType, payload);
}
//--------------------------------------------------------------------------
@@ -478,7 +473,24 @@ export class Component<T extends Env, Props extends {}> {
}
}
}
/**
* Private trigger method, allows to choose the component which triggered
* the event in the first place
*/
__trigger(component: Component<any, any>, eventType: string, payload?: any) {
if (this.el) {
const ev = new OwlEvent(component, eventType, {
bubbles: true,
cancelable: true,
detail: payload
});
const triggerHook = this.env[portalSymbol as any];
if (triggerHook) {
triggerHook(ev);
}
this.el.dispatchEvent(ev);
}
}
/**
* The __updateProps method is called by the t-component directive whenever
* it updates a component (so, when the parent template is rerendered).
+1
View File
@@ -222,6 +222,7 @@ export class Fiber {
if (this.target) {
this.target.appendChild(this.component.el!);
inDOM = document.body.contains(this.target);
this.component.env.qweb.trigger("dom-appended");
}
// call patched/mounted hook on each fiber of (reversed) patchQueue