##// END OF EJS Templates
Corrected _addChild behavior for WidgetRendition when the content is FunctionRendition which returns a widget instance
cin -
r91:a842d051d227 default
parent child
Show More
@@ -1,121 +1,128
1 1 import dom = require("dojo/dom-construct");
2 2 import { argumentNotNull } from "@implab/core-amd/safe";
3 3 import { RenditionBase } from "./RenditionBase";
4 import { DojoNodePosition, isInPage, isWidget } from "./traits";
4 import { DojoNodePosition, isElementNode, isInPage, isWidget } from "./traits";
5 5 import registry = require("dijit/registry");
6 6 import ContentPane = require("dijit/layout/ContentPane");
7 7
8 8 // tslint:disable-next-line: class-name
9 9 export interface _Widget {
10 10 domNode: Node;
11 11
12 12 containerNode?: Node;
13 13
14 14 placeAt?(refNode: string | Node, position?: DojoNodePosition): void;
15 15 startup?(): void;
16 16
17 17 addChild?(widget: any, index?: number): void;
18 18 }
19 19
20 20 export type _WidgetCtor = new (attrs: any, srcNode?: string | Node) => _Widget;
21 21
22 22 export class WidgetRendition extends RenditionBase<Node> {
23 23 readonly widgetClass: _WidgetCtor;
24 24
25 25 _instance: _Widget | undefined;
26 26
27 27 constructor(widgetClass: _WidgetCtor) {
28 28 super();
29 29 argumentNotNull(widgetClass, "widgetClass");
30 30
31 31 this.widgetClass = widgetClass;
32 32 }
33 33
34 34 _addChild(child: any): void {
35 35 const instance = this._getInstance();
36 36
37 37 if (instance.addChild) {
38 38 if (child instanceof WidgetRendition) {
39 39 // layout containers add custom logic to addChild methods
40 40 instance.addChild(child.getWidgetInstance());
41 41 } else if (isWidget(child)) {
42 42 instance.addChild(child);
43 43 } else {
44 const childDom = this.getItemDom(child);
45 const w = isElementNode(childDom) ? registry.byNode(childDom) : undefined;
46
47 if (w) {
48 instance.addChild(w);
49 } else {
44 50 if (!instance.containerNode)
45 throw new Error("The widget doesn't have neither addChild nor containerNode");
51 throw new Error("Failed to add DOM content. The widget doesn't have a containerNode");
46 52
47 53 // the current widget isn't started, it's children shouldn't start too
48 54 dom.place(this.getItemDom(child), instance.containerNode);
49 55 }
56 }
50 57 } else {
51 58 if (!instance.containerNode)
52 59 throw new Error("The widget doesn't have neither addChild nor containerNode");
53 60
54 61 // the current widget isn't started, it's children shouldn't start too
55 62 dom.place(this.getItemDom(child), instance.containerNode);
56 63 }
57 64 }
58 65
59 66 protected _create(attrs: any, children: any[]) {
60 67 if (this.widgetClass.prototype instanceof ContentPane) {
61 68 // a special case for the ContentPane this is for
62 69 // the compatibility with this heavy widget, all
63 70 // regular containers could be easily manipulated
64 71 // through `containerNode` property or `addChild` method.
65 72
66 73 // render children to the DocumentFragment
67 74 const content = document.createDocumentFragment();
68 75 children.forEach(child => content.appendChild(this.getItemDom(child)));
69 76
70 77 // set the content property to the parameters of the widget
71 78 const _attrs = { ...attrs, content };
72 79 this._instance = new this.widgetClass(_attrs);
73 80 } else {
74 81 this._instance = new this.widgetClass(attrs);
75 82 children.forEach(x => this._addChild(x));
76 83 }
77 84
78 85 }
79 86
80 87 private _getInstance() {
81 88 if (!this._instance)
82 89 throw new Error("The instance of the widget isn't created");
83 90 return this._instance;
84 91 }
85 92
86 93 protected _getDomNode() {
87 94 if (!this._instance)
88 95 throw new Error("The instance of the widget isn't created");
89 96 return this._instance.domNode;
90 97 }
91 98
92 99 /** Overrides default placeAt implementation. Calls placeAt of the
93 100 * widget and then starts it.
94 101 *
95 102 * @param refNode A node or id of the node where the widget should be placed.
96 103 * @param position A position relative to refNode.
97 104 */
98 105 placeAt(refNode: string | Node, position?: DojoNodePosition) {
99 106 this.ensureCreated();
100 107 const instance = this._getInstance();
101 108 if (typeof instance.placeAt === "function") {
102 109 instance.placeAt(refNode, position);
103 110
104 111 // fix the dojo startup behavior when the widget is placed
105 112 // directly to the document and doesn't have any enclosing widgets
106 113 const parentWidget = instance.domNode.parentNode ?
107 114 registry.getEnclosingWidget(instance.domNode.parentNode) : null
108 115 if (!parentWidget && isInPage(instance.domNode) && typeof instance.startup === "function")
109 116 instance.startup();
110 117 } else {
111 118 // the widget doesn't have a placeAt method, strange but whatever
112 119 super.placeAt(refNode, position);
113 120 }
114 121 }
115 122
116 123 getWidgetInstance() {
117 124 this.ensureCreated();
118 125 return this._getInstance();
119 126 }
120 127
121 128 }
General Comments 0
You need to be logged in to leave comments. Login now