mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] app: mount app in "first-child" position
We reintroduce the possibility to mount the app in first position in a target. The option "self" has been dropped since it is now possible for a component to have several top level nodes.
This commit is contained in:
committed by
Aaron Bohy
parent
aa3148eddf
commit
ebd2e4324f
+3
-2
@@ -1,5 +1,6 @@
|
||||
import { Component } from "./component/component";
|
||||
import { ComponentNode } from "./component/component_node";
|
||||
import { MountOptions } from "./component/fibers";
|
||||
import { Scheduler } from "./component/scheduler";
|
||||
import { TemplateSet } from "./qweb/template_helpers";
|
||||
|
||||
@@ -47,7 +48,7 @@ export class App<T extends typeof Component = any> extends TemplateSet {
|
||||
}
|
||||
}
|
||||
|
||||
mount(target: HTMLElement): Promise<InstanceType<T>> {
|
||||
mount(target: HTMLElement, options?: MountOptions): Promise<InstanceType<T>> {
|
||||
if (!(target instanceof HTMLElement)) {
|
||||
throw new Error("Cannot mount component: the target is not a valid DOM element");
|
||||
}
|
||||
@@ -56,7 +57,7 @@ export class App<T extends typeof Component = any> extends TemplateSet {
|
||||
}
|
||||
const node = new ComponentNode(this.Root, this.props, this);
|
||||
this.root = node;
|
||||
return node.mountComponent(target);
|
||||
return node.mountComponent(target, options);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
||||
@@ -23,8 +23,8 @@ export interface VNode<T = any> {
|
||||
|
||||
export type BDom = VNode<any>;
|
||||
|
||||
export function mount(vnode: VNode, fixture: HTMLElement) {
|
||||
vnode.mount(fixture, null);
|
||||
export function mount(vnode: VNode, fixture: HTMLElement, afterNode: Node | null = null) {
|
||||
vnode.mount(fixture, afterNode);
|
||||
}
|
||||
|
||||
export function patch(vnode1: VNode, vnode2: VNode, withBeforeRemove: boolean = false) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
makeChildFiber,
|
||||
makeRootFiber,
|
||||
MountFiber,
|
||||
MountOptions,
|
||||
RootFiber,
|
||||
__internal__destroyed,
|
||||
} from "./fibers";
|
||||
@@ -92,8 +93,8 @@ export class ComponentNode<T extends typeof Component = any> implements VNode<Co
|
||||
this.component.setup();
|
||||
}
|
||||
|
||||
mountComponent(target: any): Promise<InstanceType<T>> {
|
||||
const fiber = new MountFiber(this, target);
|
||||
mountComponent(target: any, options?: MountOptions): Promise<InstanceType<T>> {
|
||||
const fiber = new MountFiber(this, target, options);
|
||||
this.app.scheduler.addFiber(fiber);
|
||||
this.initiateRender(fiber);
|
||||
return fiber.promise.then(() => this.component);
|
||||
|
||||
+15
-2
@@ -158,17 +158,30 @@ export class RootFiber extends Fiber {
|
||||
|
||||
export let __internal__destroyed: ComponentNode[] = [];
|
||||
|
||||
type Position = "first-child" | "last-child";
|
||||
|
||||
export interface MountOptions {
|
||||
position?: Position;
|
||||
}
|
||||
|
||||
export class MountFiber extends RootFiber {
|
||||
target: HTMLElement;
|
||||
position: Position;
|
||||
|
||||
constructor(node: ComponentNode, target: HTMLElement) {
|
||||
constructor(node: ComponentNode, target: HTMLElement, options: MountOptions = {}) {
|
||||
super(node);
|
||||
this.target = target;
|
||||
this.position = options.position || "last-child";
|
||||
}
|
||||
complete() {
|
||||
const node = this.node;
|
||||
node.bdom = this.bdom;
|
||||
mount(node.bdom!, this.target);
|
||||
if (this.position === "last-child" || this.target.childNodes.length === 0) {
|
||||
mount(node.bdom!, this.target);
|
||||
} else {
|
||||
const firstChild = this.target.childNodes[0];
|
||||
mount(node.bdom!, this.target, firstChild);
|
||||
}
|
||||
node.status = STATUS.MOUNTED;
|
||||
this.appliedToDom = true;
|
||||
let current;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Component } from "./component";
|
||||
* Note that this method does modify in place the props
|
||||
*/
|
||||
export function applyDefaultProps(props: { [key: string]: any }, ComponentClass: typeof Component) {
|
||||
const defaultProps = (ComponentClass as any).defaultProps
|
||||
const defaultProps = (ComponentClass as any).defaultProps;
|
||||
if (defaultProps) {
|
||||
for (let propName in defaultProps) {
|
||||
if (props![propName] === undefined) {
|
||||
@@ -16,7 +16,6 @@ export function applyDefaultProps(props: { [key: string]: any }, ComponentClass:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Prop validation helper
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user