diff --git a/djx/src/main/ts/tsx/FunctionRendition.ts b/djx/src/main/ts/tsx/FunctionRendition.ts --- a/djx/src/main/ts/tsx/FunctionRendition.ts +++ b/djx/src/main/ts/tsx/FunctionRendition.ts @@ -1,5 +1,5 @@ import { argumentNotNull } from "@implab/core-amd/safe"; -import { getItemDom } from "./Renderer"; +import { getItemDom } from "./render"; import { RenditionBase } from "./RenditionBase"; import { IScope } from "./Scope"; diff --git a/djx/src/main/ts/tsx/HtmlRendition.ts b/djx/src/main/ts/tsx/HtmlRendition.ts --- a/djx/src/main/ts/tsx/HtmlRendition.ts +++ b/djx/src/main/ts/tsx/HtmlRendition.ts @@ -3,7 +3,7 @@ import { argumentNotEmptyString } from " import { RenditionBase } from "./RenditionBase"; import { placeAt } from "./traits"; import { IScope } from "./Scope"; -import { getItemDom } from "./Renderer"; +import { getItemDom } from "./render"; export class HtmlRendition extends RenditionBase { elementType: string; diff --git a/djx/src/main/ts/tsx/RenditionBase.ts b/djx/src/main/ts/tsx/RenditionBase.ts --- a/djx/src/main/ts/tsx/RenditionBase.ts +++ b/djx/src/main/ts/tsx/RenditionBase.ts @@ -2,7 +2,7 @@ import { isNull, mixin } from "@implab/c import { isPlainObject, DojoNodePosition, Rendition, isDocumentFragmentNode, placeAt, collectNodes, autostartWidgets } from "./traits"; import { IScope } from "./Scope"; -import { getScope } from "./Renderer"; +import { getScope } from "./render"; export abstract class RenditionBase implements Rendition { private _attrs = {}; diff --git a/djx/src/main/ts/tsx/WatchRendition.ts b/djx/src/main/ts/tsx/WatchRendition.ts --- a/djx/src/main/ts/tsx/WatchRendition.ts +++ b/djx/src/main/ts/tsx/WatchRendition.ts @@ -1,17 +1,15 @@ import { id as mid } from "module"; import { TraceSource } from "@implab/core-amd/log/TraceSource"; import { argumentNotNull } from "@implab/core-amd/safe"; -import { render } from "./Renderer"; +import { getItemDom, render } from "./render"; import { RenditionBase } from "./RenditionBase"; import { IScope, Scope } from "./Scope"; import { Observable } from "../observable"; const trace = TraceSource.get(mid); -const noop = () => {}; - export class WatchRendition extends RenditionBase { - private readonly _factory: (arg: T) => any; + private readonly _component: (arg: T) => unknown; private _node: Node; @@ -19,11 +17,11 @@ export class WatchRendition extends R private readonly _subject: Observable; - constructor(component: (arg: T) => any, subject: Observable) { + constructor(component: (arg: T) => unknown, subject: Observable) { super(); argumentNotNull(component, "component"); - this._factory = component; + this._component = component; this._subject = subject; @@ -35,13 +33,14 @@ export class WatchRendition extends R scope.own(this._subject.on({ next: this._onValue })); } - private _onValue = (value: T) => void this._render(value).catch( e => trace.error(e)); + private _onValue = (value: T) => + void this._render(value).catch( e => trace.error(e)); private async _render(value: T) { const prevNode = this._node; this._scope.clean(); - this._node = await render(() => this._factory(value), this._scope); + this._node = await render(this._component(value), this._scope); this.placeAt(prevNode, "replace"); } diff --git a/djx/src/main/ts/tsx/WidgetRendition.ts b/djx/src/main/ts/tsx/WidgetRendition.ts --- a/djx/src/main/ts/tsx/WidgetRendition.ts +++ b/djx/src/main/ts/tsx/WidgetRendition.ts @@ -4,7 +4,7 @@ import { DojoNodePosition, isElementNode import registry = require("dijit/registry"); import ContentPane = require("dijit/layout/ContentPane"); import { IScope } from "./Scope"; -import { getItemDom, getScope } from "./Renderer"; +import { getItemDom, getScope } from "./render"; // tslint:disable-next-line: class-name export interface _Widget { diff --git a/djx/src/main/ts/tsx/Renderer.ts b/djx/src/main/ts/tsx/render.ts rename from djx/src/main/ts/tsx/Renderer.ts rename to djx/src/main/ts/tsx/render.ts --- a/djx/src/main/ts/tsx/Renderer.ts +++ b/djx/src/main/ts/tsx/render.ts @@ -9,14 +9,19 @@ const beginRender = async () => { const endRender = () => { } +/** Returns the current scope */ export const getScope = () => _scope; -export const render = async (rendition: () => Rendition, scope = Scope.dummy) => { +/** Schedules the rendition to be rendered to the DOM Node + * @param rendition The rendition to be rendered + * @param scope The scope + */ +export const render = async (rendition: unknown, scope = Scope.dummy) => { await beginRender(); const prev = _scope; _scope = scope; try { - const node = rendition().getDomNode(); + const node = getItemDom(rendition, scope); scope.own(() => destroy(node)); return node; } finally { @@ -42,6 +47,12 @@ export const getItemDom = (v: unknown, s } else if (typeof v === "boolean" || v === null || v === undefined) { // null | undefined | boolean are removed, converted to comments return document.createComment(`[${typeof v} ${String(v)}]`); + } else if (v instanceof Array) { + // arrays will be translated to document fragments + const fragment = document.createDocumentFragment(); + v.map(item => getItemDom(item, scope)) + .forEach(node => fragment.appendChild(node)); + return fragment; } else { // bug: explicit error otherwise throw new Error("Invalid parameter: " + v);