Skip to content

Commit 5393a64

Browse files
committed
fix(renderer): attach CommentNodes to visual tree
fixes #872
1 parent e6f8c3b commit 5393a64

File tree

5 files changed

+61
-26
lines changed

5 files changed

+61
-26
lines changed

Diff for: nativescript-angular/directives/list-view-comp.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { ObservableArray } from "tns-core-modules/data/observable-array";
2525
import { LayoutBase } from "tns-core-modules/ui/layouts/layout-base";
2626
import { profile } from "tns-core-modules/profiling";
2727

28-
import { CommentNode } from "../element-registry";
28+
import { InvisibleNode } from "../element-registry";
2929
import { isListLikeIterable } from "../collection-facade";
3030
import { listViewLog, listViewError } from "../trace";
3131

@@ -217,7 +217,7 @@ export class ListViewComponent implements DoCheck, OnDestroy, AfterContentInit {
217217
}
218218

219219
function getSingleViewRecursive(nodes: Array<any>, nestLevel: number): View {
220-
const actualNodes = nodes.filter(node => !(node instanceof CommentNode));
220+
const actualNodes = nodes.filter(node => !(node instanceof InvisibleNode));
221221

222222
if (actualNodes.length === 0) {
223223
throw new Error(`No suitable views found in list template! ` +

Diff for: nativescript-angular/directives/tab-view.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from "@angular/core";
1010
import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view";
1111

12-
import { CommentNode } from "../element-registry";
12+
import { InvisibleNode } from "../element-registry";
1313
import { rendererLog } from "../trace";
1414
import { isBlank } from "../lang-facade";
1515

@@ -105,7 +105,7 @@ export class TabViewItemDirective implements OnInit {
105105
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
106106
// Filter out text nodes and comments
107107
const realViews = viewRef.rootNodes.filter(node =>
108-
!(node instanceof CommentNode));
108+
!(node instanceof InvisibleNode));
109109

110110
if (realViews.length > 0) {
111111
this.item.view = realViews[0];

Diff for: nativescript-angular/element-registry.ts

+47-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { View } from "tns-core-modules/ui/core/view";
22

33
export type NgView = (View & ViewExtensions);
4-
export type NgElement = NgView | CommentNode;
4+
export type NgElement = NgView | InvisibleNode;
55

66
export interface ViewExtensions {
77
nodeType: number;
@@ -15,12 +15,55 @@ export interface ViewClass {
1515
new (): View;
1616
}
1717

18-
// used for creating comments and text nodes in the renderer
19-
export class CommentNode {
20-
meta: { skipAddToDom: true };
18+
export abstract class InvisibleNode extends View implements ViewExtensions {
19+
meta: { skipAddToDom: boolean };
2120
templateParent: NgView;
21+
nodeType: number;
22+
nodeName: string;
23+
ngCssClasses: Map<string, boolean>;
24+
25+
constructor() {
26+
super();
27+
28+
this.nodeType = 1;
29+
this.nodeName = getClassName(this);
30+
}
31+
32+
toString() {
33+
return `${this.nodeName}(${this.id})`;
34+
}
2235
}
2336

37+
export class CommentNode extends InvisibleNode {
38+
protected static id = 0;
39+
40+
constructor() {
41+
super();
42+
43+
this.meta = {
44+
skipAddToDom: false,
45+
};
46+
this.id = CommentNode.id.toString();
47+
CommentNode.id += 1;
48+
}
49+
}
50+
51+
export class TextNode extends InvisibleNode {
52+
protected static id = 0;
53+
54+
constructor() {
55+
super();
56+
57+
this.meta = {
58+
skipAddToDom: true,
59+
};
60+
this.id = TextNode.id.toString();
61+
TextNode.id += 1;
62+
}
63+
}
64+
65+
const getClassName = instance => instance.constructor.name;
66+
2467
export interface ViewClassMeta {
2568
skipAddToDom?: boolean;
2669
insertChild?: (parent: NgView, child: NgView, atIndex: number) => void;

Diff for: nativescript-angular/renderer.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { profile } from "tns-core-modules/profiling";
1313
import { APP_ROOT_VIEW, DEVICE, getRootPage } from "./platform-providers";
1414
import { isBlank } from "./lang-facade";
1515
import { ViewUtil } from "./view-util";
16-
import { NgView, CommentNode } from "./element-registry";
16+
import { NgView, InvisibleNode } from "./element-registry";
1717
import { rendererLog as traceLog } from "./trace";
1818

1919
// CONTENT_ATTR not exported from NativeScript_renderer - we need it for styles application.
@@ -120,7 +120,7 @@ export class NativeScriptRenderer extends Renderer2 {
120120
}
121121

122122
@profile
123-
createComment(_value: any): CommentNode {
123+
createComment(_value: any): InvisibleNode {
124124
traceLog(`NativeScriptRenderer.createComment ${_value}`);
125125
return this.viewUtil.createComment();
126126
}
@@ -132,7 +132,7 @@ export class NativeScriptRenderer extends Renderer2 {
132132
}
133133

134134
@profile
135-
createText(_value: string): CommentNode {
135+
createText(_value: string): InvisibleNode {
136136
traceLog(`NativeScriptRenderer.createText ${_value}`);
137137
return this.viewUtil.createText();
138138
}

Diff for: nativescript-angular/view-util.ts

+7-15
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import { ContentView } from "tns-core-modules/ui/content-view";
55
import { LayoutBase } from "tns-core-modules/ui/layouts/layout-base";
66
import {
77
CommentNode,
8+
InvisibleNode,
89
NgElement,
910
NgView,
11+
TextNode,
1012
ViewExtensions,
1113
getViewClass,
1214
getViewMeta,
@@ -52,9 +54,8 @@ export class ViewUtil {
5254
}
5355

5456
public insertChild(parent: any, child: NgElement, atIndex: number = -1) {
55-
if (child instanceof CommentNode) {
57+
if (child instanceof InvisibleNode) {
5658
child.templateParent = parent;
57-
return;
5859
}
5960

6061
if (!parent || isDetachedElement(child)) {
@@ -79,16 +80,11 @@ export class ViewUtil {
7980
parent.content = child;
8081
} else if (parent && parent._addChildFromBuilder) {
8182
parent._addChildFromBuilder(child.nodeName, child);
82-
} else {
83-
// throw new Error("Parent can"t contain children: " + parent.nodeName + ", " + parent);
8483
}
8584
}
8685

8786
public removeChild(parent: any, child: NgElement) {
88-
if (!parent ||
89-
child instanceof CommentNode ||
90-
isDetachedElement(child)) {
91-
87+
if (!parent || isDetachedElement(child)) {
9288
return;
9389
}
9490

@@ -102,8 +98,6 @@ export class ViewUtil {
10298
}
10399
} else if (isView(parent)) {
104100
parent._removeView(child);
105-
} else {
106-
// throw new Error("Unknown parent type: " + parent);
107101
}
108102
}
109103

@@ -112,17 +106,15 @@ export class ViewUtil {
112106
return parent.getChildIndex(child);
113107
} else if (isContentView(parent)) {
114108
return child === parent.content ? 0 : -1;
115-
} else {
116-
// throw new Error("Parent can"t contain children: " + parent);
117109
}
118110
}
119111

120-
public createComment(): CommentNode {
112+
public createComment(): InvisibleNode {
121113
return new CommentNode();
122114
}
123115

124-
public createText(): CommentNode {
125-
return new CommentNode();
116+
public createText(): InvisibleNode {
117+
return new TextNode();
126118
}
127119

128120
public createView(name: string): NgView {

0 commit comments

Comments
 (0)