##// END OF EJS Templates
fixed NlsBundle locale package loading...
fixed NlsBundle locale package loading corrected DjxFragment params and return value fixed regression in DjxWidgetBase attach points processing fixed empty RenditionBase startup

File last commit:

r107:e59104632d14 default
r112:2ccfaae984e9 v1.4.4 default
Show More
WatchRendition.ts
97 lines | 2.7 KiB | video/mp2t | TypeScriptLexer
/ djx / src / main / ts / tsx / WatchRendition.ts
import { id as mid } from "module";
import { TraceSource } from "@implab/core-amd/log/TraceSource";
import { argumentNotNull } from "@implab/core-amd/safe";
import { getScope, render } from "./render";
import { RenditionBase } from "./RenditionBase";
import { Scope } from "./Scope";
import { Subscribable } from "../observable";
import { Cancellation } from "@implab/core-amd/Cancellation";
import { collectNodes, destroy, isDocumentFragmentNode, isMounted, placeAt, startupWidgets } from "./traits";
const trace = TraceSource.get(mid);
export class WatchRendition<T> extends RenditionBase<Node> {
private readonly _component: (arg: T) => unknown;
private readonly _node: Node;
private readonly _scope = new Scope();
private readonly _subject: Subscribable<T>;
private _renderJob?: { value: T };
private _ct = Cancellation.none;
constructor(component: (arg: T) => unknown, subject: Subscribable<T>) {
super();
argumentNotNull(component, "component");
this._component = component;
this._subject = subject;
this._node = document.createComment("[Watch]");
}
protected _create() {
const scope = getScope();
scope.own(() => {
this._scope.destroy();
destroy(this._node);
});
scope.own(this._subject.subscribe({ next: this._onValue }));
this._ct = new Cancellation(cancel => scope.own(cancel));
}
private readonly _onValue = (value: T) => {
if (!this._renderJob) {
// schedule a new job
this._renderJob = { value };
this._render().catch(e => trace.error(e));
} else {
// update existing job
this._renderJob = { value };
}
};
private async _render() {
// fork
await Promise.resolve();
// don't render destroyed rendition
if (this._ct.isRequested())
return;
// remove all previous content
this._scope.clean();
// render the new node
const node = render(
this._renderJob ? this._component(this._renderJob.value) : undefined,
this._scope
);
// get actual content
const pending = isDocumentFragmentNode(node) ?
collectNodes(node.childNodes) :
[node];
placeAt(node, this._node, "after");
if (isMounted(this._node))
pending.forEach(n => startupWidgets(n));
if (pending.length)
this._scope.own(() => pending.forEach(destroy));
this._renderJob = undefined;
}
protected _getDomNode() {
if (!this._node)
throw new Error("The instance of the widget isn't created");
return this._node;
}
}