##// END OF EJS Templates
corrected tear down logic handling in observables. Added support for observable query results
corrected tear down logic handling in observables. Added support for observable query results

File last commit:

r109:4a375b9c654a default
r110:1a190b3a757d v1.4.0 default
Show More
DjxWidgetBase.ts
131 lines | 4.7 KiB | video/mp2t | TypeScriptLexer
/ djx / src / main / ts / tsx / DjxWidgetBase.ts
import { djbase, djclass } from "../declare";
import _WidgetBase = require("dijit/_WidgetBase");
import _AttachMixin = require("dijit/_AttachMixin");
import { Rendition, isNode, isElementNode } from "./traits";
import registry = require("dijit/registry");
import on = require("dojo/on");
import { Scope } from "./Scope";
import { render } from "./render";
// type Handle = dojo.Handle;
export interface EventArgs {
bubbles?: boolean;
cancelable?: boolean;
composed?: boolean;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export interface DjxWidgetBase<Attrs = object, Events extends { [name in keyof Events]: Event } = object> extends
_WidgetBase<Events> {
/** This property is declared only for type inference to work, it is never assigned
* and should not be used.
*/
readonly _eventMap: Events & GlobalEventHandlersEventMap;
/** The list of pairs of event and method names. When the widget is created all methods from
* this list will be connected to corresponding events.
*
* This property is maintained in the prototype
*/
_eventHandlers: Array<{
eventName: string,
handlerMethod: string;
}>;
}
type _super = {
startup(): void;
destroy(preserveDom?: boolean): void;
};
@djclass
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export abstract class DjxWidgetBase<Attrs = object, Events = object> extends djbase<_super, _AttachMixin>(_WidgetBase, _AttachMixin) {
private readonly _scope = new Scope();
buildRendering() {
const node = render(this.render(), this._scope);
if (!isElementNode(node))
throw new Error("The render method must return a single DOM element");
this.domNode = node as HTMLElement;
super.buildRendering();
// now we should get assigned data-dojo-attach-points
// place the contents of the original srcNode to the containerNode
const src = this.srcNodeRef;
const dest = this.containerNode;
// the donNode is constructed now we need to connect event handlers
this._connectEventHandlers();
if (src && dest) {
while (src.firstChild)
dest.appendChild(src.firstChild);
}
}
abstract render(): Rendition;
private _connectEventHandlers() {
if (this._eventHandlers)
this._eventHandlers.forEach(({ eventName, handlerMethod }) => {
const handler = this[handlerMethod as keyof this];
if (typeof handler === "function")
on(this.domNode, eventName, handler.bind(this) as (...args: unknown[]) => unknown);
});
}
_processTemplateNode<T extends (Element | Node | _WidgetBase)>(
baseNode: T,
getAttrFunc: (baseNode: T, attr: string) => string,
// tslint:disable-next-line: ban-types
attachFunc: (node: T, type: string, func?: (...args: unknown[]) => unknown) => dojo.Handle
): boolean {
if (isNode(baseNode)) {
const w = registry.byNode(baseNode);
if (w) {
// from dijit/_WidgetsInTemplateMixin
this._processTemplateNode(w,
(n, p) => String(n.get(p as keyof typeof n)), // callback to get a property of a widget
(widget, type, callback) => {
if (!callback)
throw new Error("The callback must be specified");
// callback to do data-dojo-attach-event to a widget
if (type in widget) {
// back-compat, remove for 2.0
return widget.connect(widget, type, callback as EventListener);
} else {
// 1.x may never hit this branch, but it's the default for 2.0
return widget.on(type as keyof GlobalEventHandlersEventMap, callback);
}
});
// don't process widgets internals
return false;
}
}
// eslint-disable-next-line @typescript-eslint/ban-types
return super._processTemplateNode(baseNode, getAttrFunc, attachFunc as (node: T, type: string, func?: Function) => dojo.Handle);
}
/** Starts current widget and all its supporting widgets (placed outside
* `containerNode`) and child widgets (placed inside `containerNode`)
*/
startup() {
// startup supporting widgets
registry.findWidgets(this.domNode, this.containerNode).forEach(w => w.startup());
super.startup();
}
destroy(preserveDom?: boolean) {
this._scope.destroy();
super.destroy(preserveDom);
}
}