##// END OF EJS Templates
temp commit, working on @on() decorator
cin -
r72:3ef812269f4f default
parent child
Show More
@@ -1,35 +1,34
1 {
1 {
2 "name": "@implab/djx",
2 "name": "@implab/djx",
3 "version": "0.0.1-dev",
3 "version": "0.0.1-dev",
4 "description": "Supports using dojo version 1 with typescript and .tsx files",
4 "description": "Supports using dojo version 1 with typescript and .tsx files",
5 "keywords": [
5 "keywords": [
6 "dojo",
6 "dojo",
7 "tsx",
7 "tsx",
8 "typescript",
8 "typescript",
9 "widgets"
9 "widgets"
10 ],
10 ],
11 "author": "Implab team",
11 "author": "Implab team",
12 "license": "BSD-2-Clause",
12 "license": "BSD-2-Clause",
13 "repository": "https://code.implab.org/implab/implabjs-djx",
13 "repository": "https://code.implab.org/implab/implabjs-djx",
14 "publishConfig": {
14 "publishConfig": {
15 "access": "public"
15 "access": "public"
16 },
16 },
17 "peerDependencies": {
17 "peerDependencies": {
18 "@implab/core-amd": "^1.4.0",
18 "@implab/core-amd": "^1.4.0",
19 "dojo": "^1.10.0"
19 "dojo": "^1.10.0"
20 },
20 },
21 "devDependencies": {
21 "devDependencies": {
22 "@implab/core-amd": "^1.4.0",
22 "@implab/core-amd": "^1.4.0",
23 "@types/chai": "4.1.3",
23 "@types/chai": "4.1.3",
24 "@types/requirejs": "2.1.31",
24 "@types/requirejs": "2.1.31",
25 "@types/yaml": "1.2.0",
25 "@types/yaml": "1.2.0",
26 "chai": "4.2.0",
27 "dojo": "1.16.0",
26 "dojo": "1.16.0",
28 "@implab/dojo-typings": "/home/sergey/projects/implabjs-dojo-typings/dojo-typings/build/npm/package/implab-dojo-typings-v1.0.0-rc4.tgz",
27 "@implab/dojo-typings": "1.0.0",
29 "eslint": "6.8.0",
28 "eslint": "6.8.0",
30 "requirejs": "2.3.6",
29 "requirejs": "2.3.6",
31 "tslint": "^6.1.3",
30 "tslint": "^6.1.3",
32 "typescript": "4.2.4",
31 "typescript": "4.2.4",
33 "yaml": "~1.7.2"
32 "yaml": "~1.7.2"
34 }
33 }
35 }
34 }
@@ -1,86 +1,100
1 import { AbstractConstructor, djbase, djclass } from "../declare";
1 import { AbstractConstructor, djbase, djclass } from "../declare";
2 import _WidgetBase = require("dijit/_WidgetBase");
2 import _WidgetBase = require("dijit/_WidgetBase");
3 import _AttachMixin = require("dijit/_AttachMixin");
3 import _AttachMixin = require("dijit/_AttachMixin");
4 import { Rendition, isNode, startupWidgets } from "./traits";
4 import { Rendition, isNode, startupWidgets } from "./traits";
5 import registry = require("dijit/registry");
5 import registry = require("dijit/registry");
6
6
7 // type Handle = dojo.Handle;
7 // type Handle = dojo.Handle;
8
8
9 export interface EventArgs {
9 export interface EventArgs {
10 bubbles?: boolean;
10 bubbles?: boolean;
11
11
12 cancelable?: boolean;
12 cancelable?: boolean;
13
13
14 composed?: boolean;
14 composed?: boolean;
15 }
15 }
16
16
17 export interface DjxWidgetBase<Attrs = {}, Events extends { [name in keyof Events]: Event } = {}> extends
17 export interface DjxWidgetBase<Attrs = {}, Events extends { [name in keyof Events]: Event } = {}> extends
18 _WidgetBase<Events> {
18 _WidgetBase<Events> {
19
20 readonly _eventMap: Events & GlobalEventHandlersEventMap;
19 }
21 }
20
22
21 type _super = {
23 type _super = {
22 startup(): void;
24 startup(): void;
23 }
25 }
24
26
25 @djclass
27 @djclass
26 export abstract class DjxWidgetBase<Attrs = {}, Events = {}> extends djbase<_super, _AttachMixin>(_WidgetBase, _AttachMixin) {
28 export abstract class DjxWidgetBase<Attrs = {}, Events = {}> extends djbase<_super, _AttachMixin>(_WidgetBase, _AttachMixin) {
27
29
30 _eventHandlers: Array<{
31 eventName: keyof Events,
32 handlerMethod: string;
33 }> = [];
34
28 buildRendering() {
35 buildRendering() {
29 this.domNode = this.render().getDomNode();
36 this.domNode = this.render().getDomNode();
30 super.buildRendering();
37 super.buildRendering();
31
38
32 // now we should get assigned data-dojo-attach-points
39 // now we should get assigned data-dojo-attach-points
33 // place the contents of the original srcNode to the containerNode
40 // place the contents of the original srcNode to the containerNode
34 const src = this.srcNodeRef;
41 const src = this.srcNodeRef;
35 const dest = this.containerNode;
42 const dest = this.containerNode;
36
43
37 if (src && dest) {
44 if (src && dest) {
38 while (src.firstChild)
45 while (src.firstChild)
39 dest.appendChild(src.firstChild);
46 dest.appendChild(src.firstChild);
40 }
47 }
41 }
48 }
42
49
43 abstract render(): Rendition<HTMLElement>;
50 abstract render(): Rendition<HTMLElement>;
44
51
52 private _connectEventHandlers() {
53 this._eventHandlers.forEach(({eventName, handlerMethod}) => {
54 if (typeof this[handlerMethod as keyof this] === "function")
55 this.on(eventName, this[handlerMethod] as Function);
56 });
57 }
58
45 _processTemplateNode<T extends (Element | Node | _WidgetBase)>(
59 _processTemplateNode<T extends (Element | Node | _WidgetBase)>(
46 baseNode: T,
60 baseNode: T,
47 getAttrFunc: (baseNode: T, attr: string) => any,
61 getAttrFunc: (baseNode: T, attr: string) => any,
48 // tslint:disable-next-line: ban-types
62 // tslint:disable-next-line: ban-types
49 attachFunc: (node: T, type: string, func?: Function) => dojo.Handle
63 attachFunc: (node: T, type: string, func?: Function) => dojo.Handle
50 ): boolean {
64 ): boolean {
51 if (isNode(baseNode)) {
65 if (isNode(baseNode)) {
52 const w = registry.byNode(baseNode);
66 const w = registry.byNode(baseNode);
53 if (w) {
67 if (w) {
54 // from dijit/_WidgetsInTemplateMixin
68 // from dijit/_WidgetsInTemplateMixin
55 this._processTemplateNode(w,
69 this._processTemplateNode(w,
56 (n, p) => n.get(p as any), // callback to get a property of a widget
70 (n, p) => n.get(p as any), // callback to get a property of a widget
57 (widget, type, callback) => {
71 (widget, type, callback) => {
58 if (!callback)
72 if (!callback)
59 throw new Error("The callback must be specified");
73 throw new Error("The callback must be specified");
60
74
61 // callback to do data-dojo-attach-event to a widget
75 // callback to do data-dojo-attach-event to a widget
62 if (type in widget) {
76 if (type in widget) {
63 // back-compat, remove for 2.0
77 // back-compat, remove for 2.0
64 return widget.connect(widget, type, callback as EventListener);
78 return widget.connect(widget, type, callback as EventListener);
65 } else {
79 } else {
66 // 1.x may never hit this branch, but it's the default for 2.0
80 // 1.x may never hit this branch, but it's the default for 2.0
67 return widget.on(type, callback);
81 return widget.on(type, callback);
68 }
82 }
69
83
70 });
84 });
71 // don't process widgets internals
85 // don't process widgets internals
72 return false;
86 return false;
73 }
87 }
74 }
88 }
75 return super._processTemplateNode(baseNode, getAttrFunc, attachFunc);
89 return super._processTemplateNode(baseNode, getAttrFunc, attachFunc);
76 }
90 }
77
91
78 /** Starts current widget and all its supporting widgets (placed outside
92 /** Starts current widget and all its supporting widgets (placed outside
79 * `containerNode`) and child widgets (placed inside `containerNode`)
93 * `containerNode`) and child widgets (placed inside `containerNode`)
80 */
94 */
81 startup() {
95 startup() {
82 // startup supporting widgets
96 // startup supporting widgets
83 registry.findWidgets(this.domNode, this.containerNode).forEach(w => w.startup());
97 registry.findWidgets(this.domNode, this.containerNode).forEach(w => w.startup());
84 super.startup();
98 super.startup();
85 }
99 }
86 }
100 }
@@ -1,204 +1,222
1 import { IDestroyable, IRemovable } from "@implab/core-amd/interfaces";
1 import { IDestroyable, IRemovable } from "@implab/core-amd/interfaces";
2 import { isDestroyable } from "@implab/core-amd/safe";
2 import { isDestroyable } from "@implab/core-amd/safe";
3 import _WidgetBase = require("dijit/_WidgetBase");
3 import _WidgetBase = require("dijit/_WidgetBase");
4 import registry = require("dijit/registry");
4 import registry = require("dijit/registry");
5 import dom = require("dojo/dom-construct");
5 import dom = require("dojo/dom-construct");
6 import Stateful = require("dojo/Stateful");
6 import Stateful = require("dojo/Stateful");
7 import { FunctionRendition } from "./FunctionRendition";
7 import { FunctionRendition } from "./FunctionRendition";
8 import { DjxWidgetBase } from "./DjxWidgetBase";
8
9
9 type _WidgetBaseConstructor = typeof _WidgetBase;
10 type _WidgetBaseConstructor = typeof _WidgetBase;
10
11
11 export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number;
12 export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number;
12
13
13 export interface Rendition<TNode extends Node = Node> {
14 export interface Rendition<TNode extends Node = Node> {
14 getDomNode(): TNode;
15 getDomNode(): TNode;
15
16
16 placeAt(refNode: string | Node, position?: DojoNodePosition): void;
17 placeAt(refNode: string | Node, position?: DojoNodePosition): void;
17 }
18 }
18
19
19 /**
20 /**
20 * @deprecated use Rendition
21 * @deprecated use Rendition
21 */
22 */
22 export type BuildContext<TNode extends Node = Node> = Rendition<TNode>;
23 export type BuildContext<TNode extends Node = Node> = Rendition<TNode>;
23
24
24 export interface IRecursivelyDestroyable {
25 export interface IRecursivelyDestroyable {
25 destroyRecursive(): void;
26 destroyRecursive(): void;
26 }
27 }
27
28
28 export function isNode(el: any): el is Node {
29 export function isNode(el: any): el is Node {
29 return el && el.nodeName && el.nodeType;
30 return el && el.nodeName && el.nodeType;
30 }
31 }
31
32
32 export function isElementNode(el: any): el is Element {
33 export function isElementNode(el: any): el is Element {
33 return isNode(el) && el.nodeType === 1;
34 return isNode(el) && el.nodeType === 1;
34 }
35 }
35
36
36 export function isTextNode(el: any): el is Text {
37 export function isTextNode(el: any): el is Text {
37 return isNode(el) && el.nodeType === 3;
38 return isNode(el) && el.nodeType === 3;
38 }
39 }
39
40
40 export function isProcessingInstructionNode(el: any): el is ProcessingInstruction {
41 export function isProcessingInstructionNode(el: any): el is ProcessingInstruction {
41 return isNode(el) && el.nodeType === 7;
42 return isNode(el) && el.nodeType === 7;
42 }
43 }
43
44
44 export function isCommentNode(el: any): el is Comment {
45 export function isCommentNode(el: any): el is Comment {
45 return isNode(el) && el.nodeType === 8;
46 return isNode(el) && el.nodeType === 8;
46 }
47 }
47
48
48 export function isDocumentNode(el: any): el is Document {
49 export function isDocumentNode(el: any): el is Document {
49 return isNode(el) && el.nodeType === 9;
50 return isNode(el) && el.nodeType === 9;
50 }
51 }
51
52
52 export function isDocumentTypeNode(el: any): el is DocumentType {
53 export function isDocumentTypeNode(el: any): el is DocumentType {
53 return isNode(el) && el.nodeType === 10;
54 return isNode(el) && el.nodeType === 10;
54 }
55 }
55
56
56 export function isDocumentFragmentNode(el: any): el is DocumentFragment {
57 export function isDocumentFragmentNode(el: any): el is DocumentFragment {
57 return isNode(el) && el.nodeType === 11;
58 return isNode(el) && el.nodeType === 11;
58 }
59 }
59
60
60 export function isWidget(v: any): v is _WidgetBase {
61 export function isWidget(v: any): v is _WidgetBase {
61 return v && "domNode" in v;
62 return v && "domNode" in v;
62 }
63 }
63
64
64 export function isRendition(v: any): v is Rendition {
65 export function isRendition(v: any): v is Rendition {
65 return typeof v === "object" && typeof v.getDomElement === "function";
66 return typeof v === "object" && typeof v.getDomElement === "function";
66 }
67 }
67
68
68 /**
69 /**
69 * @deprecated use isRendition
70 * @deprecated use isRendition
70 */
71 */
71 export const isBuildContext = isRendition;
72 export const isBuildContext = isRendition;
72
73
73 export function isPlainObject(v: object) {
74 export function isPlainObject(v: object) {
74 if (typeof v !== "object")
75 if (typeof v !== "object")
75 return false;
76 return false;
76
77
77 const vp = Object.getPrototypeOf(v);
78 const vp = Object.getPrototypeOf(v);
78 return !vp || vp === Object.prototype;
79 return !vp || vp === Object.prototype;
79 }
80 }
80
81
81 export function isWidgetConstructor(v: any): v is _WidgetBaseConstructor {
82 export function isWidgetConstructor(v: any): v is _WidgetBaseConstructor {
82 return typeof v === "function" && v.prototype && (
83 return typeof v === "function" && v.prototype && (
83 "domNode" in v.prototype ||
84 "domNode" in v.prototype ||
84 "buildRendering" in v.prototype
85 "buildRendering" in v.prototype
85 );
86 );
86 }
87 }
87
88
88 /** Tests whether the specified node is placed in visible dom.
89 /** Tests whether the specified node is placed in visible dom.
89 * @param {Node} node The node to test
90 * @param {Node} node The node to test
90 */
91 */
91 export function isInPage(node: Node) {
92 export function isInPage(node: Node) {
92 return (node === document.body) ? false : document.body.contains(node);
93 return (node === document.body) ? false : document.body.contains(node);
93 }
94 }
94
95
95 export function isRecursivelyDestroyable(target: any): target is IRecursivelyDestroyable {
96 export function isRecursivelyDestroyable(target: any): target is IRecursivelyDestroyable {
96 return target && typeof target.destroyRecursive === "function";
97 return target && typeof target.destroyRecursive === "function";
97 }
98 }
98
99
99
100
100 /** Destroys DOM Node with all contained widgets.
101 /** Destroys DOM Node with all contained widgets.
101 * If the specified node is the root node of a widget, then the
102 * If the specified node is the root node of a widget, then the
102 * widget will be destroyed.
103 * widget will be destroyed.
103 *
104 *
104 * @param target DOM Node or widget to destroy
105 * @param target DOM Node or widget to destroy
105 */
106 */
106 export function destroy(target: Node | IDestroyable | IRecursivelyDestroyable) {
107 export function destroy(target: Node | IDestroyable | IRecursivelyDestroyable) {
107 if (isRecursivelyDestroyable(target)) {
108 if (isRecursivelyDestroyable(target)) {
108 target.destroyRecursive();
109 target.destroyRecursive();
109 } else if (isDestroyable(target)) {
110 } else if (isDestroyable(target)) {
110 target.destroy();
111 target.destroy();
111 } else if (isNode(target)) {
112 } else if (isNode(target)) {
112 const self = registry.byNode(target);
113 const self = registry.byNode(target);
113 if (self) {
114 if (self) {
114 self.destroyRecursive();
115 self.destroyRecursive();
115 } else {
116 } else {
116 registry.findWidgets(target).forEach(destroy);
117 registry.findWidgets(target).forEach(destroy);
117 dom.destroy(target);
118 dom.destroy(target);
118 }
119 }
119 }
120 }
120 }
121 }
121
122
122 /** Empties a content of the specified node and destroys all contained widgets.
123 /** Empties a content of the specified node and destroys all contained widgets.
123 *
124 *
124 * @param target DOM node to .
125 * @param target DOM node to .
125 */
126 */
126 export function emptyNode(target: Node) {
127 export function emptyNode(target: Node) {
127 registry.findWidgets(target).forEach(destroy);
128 registry.findWidgets(target).forEach(destroy);
128 dom.empty(target);
129 dom.empty(target);
129 }
130 }
130
131
131 /** This function starts all widgets inside the DOM node if the target is a node
132 /** This function starts all widgets inside the DOM node if the target is a node
132 * or starts widget itself if the target is the widget. If the specified node
133 * or starts widget itself if the target is the widget. If the specified node
133 * associated with the widget that widget will be started.
134 * associated with the widget that widget will be started.
134 *
135 *
135 * @param target DOM node to find and start widgets or the widget itself.
136 * @param target DOM node to find and start widgets or the widget itself.
136 */
137 */
137 export function startupWidgets(target: Node | _WidgetBase, skipNode?: Node) {
138 export function startupWidgets(target: Node | _WidgetBase, skipNode?: Node) {
138 if (isNode(target)) {
139 if (isNode(target)) {
139 const w = isElementNode(target) ? registry.byNode(target) : undefined;
140 const w = isElementNode(target) ? registry.byNode(target) : undefined;
140 if (w) {
141 if (w) {
141 if (w.startup)
142 if (w.startup)
142 w.startup();
143 w.startup();
143 } else {
144 } else {
144 registry.findWidgets(target, skipNode).forEach(x => x.startup());
145 registry.findWidgets(target, skipNode).forEach(x => x.startup());
145 }
146 }
146 } else {
147 } else {
147 if(target.startup)
148 if (target.startup)
148 target.startup();
149 target.startup();
149 }
150 }
150 }
151 }
151
152
152
153
153 type StatefulProps<T> = T extends Stateful<infer A> ? A : never;
154 type StatefulProps<T> = T extends Stateful<infer A> ? A : never;
154
155
155 type CleanFn = (instance: IRemovable | IDestroyable) => void;
156 type CleanFn = (instance: IRemovable | IDestroyable) => void;
156
157
157 /**
158 /**
158 * Observers the property and calls render callback each change.
159 * Observers the property and calls render callback each change.
159 *
160 *
160 * @param target The target object which property will be observed.
161 * @param target The target object which property will be observed.
161 * @param prop The name of the property.
162 * @param prop The name of the property.
162 * @param render The callback which will be called every time the value is changed
163 * @param render The callback which will be called every time the value is changed
163 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
164 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
164 * @returns Rendition which is created instantly
165 * @returns Rendition which is created instantly
165 */
166 */
166 export function watch<W extends _WidgetBase, K extends keyof W> (
167 export function watch<W extends _WidgetBase, K extends keyof W>(
167 target: W,
168 target: W,
168 prop: K,
169 prop: K,
169 render: (model: W[K]) => any,
170 render: (model: W[K]) => any,
170 cleanupOrOwner?: {own: CleanFn} | CleanFn
171 cleanupOrOwner?: { own: CleanFn } | CleanFn
171 ): Rendition;
172 ): Rendition;
172 /**
173 /**
173 * Observers the property and calls render callback each change.
174 * Observers the property and calls render callback each change.
174 *
175 *
175 * @param target The target object which property will be observed.
176 * @param target The target object which property will be observed.
176 * @param prop The name of the property.
177 * @param prop The name of the property.
177 * @param render The callback which will be called every time the value is changed
178 * @param render The callback which will be called every time the value is changed
178 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
179 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
179 * @returns Rendition which is created instantly
180 * @returns Rendition which is created instantly
180 */
181 */
181 export function watch<T extends Stateful, K extends keyof StatefulProps<T>>(
182 export function watch<T extends Stateful, K extends keyof StatefulProps<T>>(
182 target: T,
183 target: T,
183 prop: K,
184 prop: K,
184 render: (model: StatefulProps<T>[K]) => any,
185 render: (model: StatefulProps<T>[K]) => any,
185 cleanupOrOwner?: {own: CleanFn} | CleanFn
186 cleanupOrOwner?: { own: CleanFn } | CleanFn
186 ): Rendition;
187 ): Rendition;
187 export function watch<T extends Stateful, K extends keyof StatefulProps<T> & string>(
188 export function watch<T extends Stateful, K extends keyof StatefulProps<T> & string>(
188 target: T,
189 target: T,
189 prop: K,
190 prop: K,
190 render: (model: StatefulProps<T>[K]) => any,
191 render: (model: StatefulProps<T>[K]) => any,
191 cleanupOrOwner: {own: CleanFn} | CleanFn = () => {}
192 cleanupOrOwner: { own: CleanFn } | CleanFn = () => { }
192 ) {
193 ) {
193 let rendition = new FunctionRendition(() => render(target.get(prop)));
194 let rendition = new FunctionRendition(() => render(target.get(prop)));
194 const _own = cleanupOrOwner instanceof Function ? cleanupOrOwner : (x: IRemovable) => cleanupOrOwner.own(x)
195 const _own = cleanupOrOwner instanceof Function ? cleanupOrOwner : (x: IRemovable) => cleanupOrOwner.own(x)
195 _own(target.watch(prop, (_name, oldValue, newValue) => {
196 _own(target.watch(prop, (_name, oldValue, newValue) => {
196 if (oldValue !== newValue) {
197 if (oldValue !== newValue) {
197 const newRendition = new FunctionRendition(() => render(newValue));
198 const newRendition = new FunctionRendition(() => render(newValue));
198 newRendition.placeAt(rendition.getDomNode(), "replace");
199 newRendition.placeAt(rendition.getDomNode(), "replace");
199 destroy(rendition.getDomNode());
200 destroy(rendition.getDomNode());
200 rendition = newRendition;
201 rendition = newRendition;
201 }
202 }
202 }));
203 }));
203 return rendition;
204 return rendition;
204 }
205 }
206
207 export type WidgetEvents<W> = W extends DjxWidgetBase<any, infer EM> ? EM : never;
208
209 export type HandlerType<W, E extends keyof any> = W extends {
210 on(eventName: E, handler: infer H): any;
211 } ? H : never;
212
213 export const on = <E extends keyof any>(eventName: E) =>
214 <K extends keyof T,
215 T extends DjxWidgetBase
216 >(
217 target: T,
218 key: K,
219 descriptor: PropertyDescriptor
220 ): any => {
221 target.
222 };
@@ -1,55 +1,73
1 import { djbase, djclass, bind, prototype, AbstractConstructor } from "../declare";
1 import { djbase, djclass, bind, prototype, AbstractConstructor } from "../declare";
2
2
3 import { DjxWidgetBase } from "../tsx/DjxWidgetBase";
3 import { DjxWidgetBase } from "../tsx/DjxWidgetBase";
4 import { createElement } from "../tsx";
4 import { createElement } from "../tsx";
5 import { HandlerType, on, WidgetEvents } from "../tsx/traits";
5
6
6 interface MyWidgetAttrs {
7 interface MyWidgetAttrs {
7 title: string;
8 title: string;
8
9
9 counter: number;
10 counter: number;
10 }
11 }
11
12
12 interface MyWidgetEvents {
13 interface MyWidgetEvents {
13 "count-inc": Event & {
14 "count-inc": Event & {
14 detail: number;
15 detail: number;
15 };
16 };
16
17
17 "count-dec": Event & {
18 "count-dec": Event & {
18 detail: number;
19 detail: number;
19 };
20 };
20 }
21 }
21
22
22
23
23 @djclass
24 @djclass
24 export class MyWidget extends djbase(DjxWidgetBase as AbstractConstructor<DjxWidgetBase<MyWidgetAttrs, MyWidgetEvents>>) {
25 export class MyWidget extends djbase(DjxWidgetBase as AbstractConstructor<DjxWidgetBase<MyWidgetAttrs, MyWidgetEvents>>) {
25
26
26 @bind({ node: "titleNode", type: "innerHTML" })
27 @bind({ node: "titleNode", type: "innerHTML" })
27 title = "";
28 title = "";
28
29
29 @prototype()
30 @prototype()
30 counter = 0;
31 counter = 0;
31
32
32 render() {
33 render() {
33 const Frame = (props: any) => <div>{props.children}</div>;
34 const Frame = (props: any) => <div>{props.children}</div>;
34 return <div className="myWidget" onsubmit={e => this._onSubmit(e)} tabIndex={3} style={{ alignContent: "center", border: "1px solid" }} >
35 return <div className="myWidget" onsubmit={e => this._onSubmit(e)} tabIndex={3} style={{ alignContent: "center", border: "1px solid" }} >
35 <h1 data-dojo-attach-point="titleNode"></h1>
36 <h1 data-dojo-attach-point="titleNode"></h1>
36 <Frame>
37 <Frame>
37 <span class="up-button" onclick={e => this._onIncClick(e)}>[+]</span>
38 <span class="up-button" onclick={e => this._onIncClick(e)}>[+]</span>
38 <span class="down-button" onclick={() => this._onDecClick()}>[-]</span>
39 <span class="down-button" onclick={() => this._onDecClick()}>[-]</span>
39 </Frame>
40 </Frame>
40 </div>;
41 </div>;
41 }
42 }
42
43
44 postCreate() {
45 super.postCreate();
46
47 this.on("click", () => {});
48 }
49
43 _onSubmit(e: Event) {
50 _onSubmit(e: Event) {
44 }
51 }
45
52
46 _onIncClick(e: MouseEvent) {
53 _onIncClick(e: MouseEvent) {
47 this.set("counter", this.counter+1);
54 this.set("counter", this.counter + 1);
48
55
49 this.emit("count-inc", { bubbles: false });
56 this.emit("count-inc", { bubbles: false });
50 }
57 }
51
58
52 _onDecClick() {
59 _onDecClick() {
53 this.emit("count-dec", { bubbles: false, detail: this.counter });
60 this.emit("count-dec", { bubbles: false, detail: this.counter });
54 }
61 }
62
63 @on("count-inc")
64 _onCounterInc(evt: Event & { detail: number; }) {
65
55 }
66 }
67 }
68
69 declare const w: MyWidget;
70 w.on("click", () => {});
71
72 declare const ev: WidgetEvents<MyWidget>;
73 ev["count-inc"];
@@ -1,13 +1,14
1 {
1 {
2 "compilerOptions": {
2 "compilerOptions": {
3 "moduleResolution": "node",
3 "moduleResolution": "node",
4 "noEmitOnError": true,
4 "noEmitOnError": true,
5 "strict": true,
5 "strict": true,
6 "types": [],
6 "types": [],
7 "experimentalDecorators": true,
7 "experimentalDecorators": true,
8 "jsxFactory": "createElement",
8 "jsxFactory": "createElement",
9 "target": "ES5",
9 //"skipLibCheck": true,
10 //"skipLibCheck": true,
10 "jsx": "react",
11 "jsx": "react",
11 "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"]
12 "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"]
12 }
13 }
13 } No newline at end of file
14 }
General Comments 0
You need to be logged in to leave comments. Login now