Skip to content

Commit ab2eabf

Browse files
author
Alexander Vakrilov
committed
Merge pull request #24 from NativeScript/feature/complex-properties
Support setting complex properties - e.x. TabViewItems
2 parents a60182a + 7b57827 commit ab2eabf

File tree

6 files changed

+145
-83
lines changed

6 files changed

+145
-83
lines changed

Diff for: ng-sample/app/app.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import "globals";
2-
import "./modules";
3-
2+
// import "./modules";
43
global.registerModule("./main-page", function () { return require("./main-page"); });
54

65
import * as profiling from "./profiling";

Diff for: ng-sample/app/package.json

+24-23
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
{
2-
"name": "tns-template-hello-world",
3-
"version": "1.2.0",
4-
"author": "Telerik <[email protected]>",
5-
"description": "Nativescript hello-world project template",
6-
"license": "BSD",
7-
"keywords": [
8-
"telerik",
9-
"mobile",
10-
"nativescript",
11-
"{N}",
12-
"tns",
13-
"appbuilder",
14-
"template"
15-
],
16-
"repository": {
17-
"type": "git",
18-
"url": "git://github.com/NativeScript/template-hello-world.git"
19-
},
20-
"bugs": {
21-
"url": "https://github.com/NativeScript/template-hello-world/issues"
22-
},
23-
"homepage": "https://github.com/NativeScript/template-hello-world"
24-
}
2+
"name": "tns-template-hello-world",
3+
"main": "app.js",
4+
"version": "1.2.0",
5+
"author": "Telerik <[email protected]>",
6+
"description": "Nativescript hello-world project template",
7+
"license": "BSD",
8+
"keywords": [
9+
"telerik",
10+
"mobile",
11+
"nativescript",
12+
"{N}",
13+
"tns",
14+
"appbuilder",
15+
"template"
16+
],
17+
"repository": {
18+
"type": "git",
19+
"url": "git://github.com/NativeScript/template-hello-world.git"
20+
},
21+
"bugs": {
22+
"url": "https://github.com/NativeScript/template-hello-world/issues"
23+
},
24+
"homepage": "https://github.com/NativeScript/template-hello-world"
25+
}

Diff for: ng-sample/app/renderer-test.ts

+27-14
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,33 @@ export class TemplatedComponent {
1212
})
1313
@View({
1414
directives: [NgIf, NgFor, TemplatedComponent],
15-
template: `
16-
<StackLayout orientation='vertical'>
17-
<templated-component></templated-component>
18-
<Label [class.valid]="isValid" [class.invalid]="!isValid" text='Name' fontSize='20' verticalAlignment='center' padding='20'></Label>
19-
<TextField #name text='John' fontSize='20' padding='20'></TextField>
20-
<Button [text]='buttonText' (tap)='onSave($event, name.text, $el)'></Button>
21-
<Button text='Toggle details' (tap)='onToggleDetails()'></Button>
22-
<TextView *ng-if='showDetails' [text]='detailsText'></TextView>
23-
<Label text='==============================' fontSize='20'></Label>
24-
<StackLayout #more *ng-if='showDetails' orientation='vertical'>
25-
<TextField *ng-for='#detailLine of detailLines' [text]='detailLine'></TextField>
26-
</StackLayout>
27-
<Label text='==============================' fontSize='20'></Label>
28-
</StackLayout>
15+
template: `
16+
<TabView>
17+
<TabView.items>
18+
<TabViewItem title="First Tab">
19+
<TabViewItem.view>
20+
<StackLayout orientation='vertical'>
21+
<templated-component></templated-component>
22+
<Label [class.valid]="isValid" [class.invalid]="!isValid" text='Name' fontSize='20' verticalAlignment='center' padding='20'></Label>
23+
<TextField #name text='John' fontSize='20' padding='20'></TextField>
24+
<Button [text]='buttonText' (tap)='onSave($event, name.text, $el)'></Button>
25+
<Button text='Toggle details' (tap)='onToggleDetails()'></Button>
26+
<TextView *ng-if='showDetails' [text]='detailsText'></TextView>
27+
<Label text='==============================' fontSize='20'></Label>
28+
<StackLayout #more *ng-if='showDetails' orientation='vertical'>
29+
<TextField *ng-for='#detailLine of detailLines' [text]='detailLine'></TextField>
30+
</StackLayout>
31+
<Label text='==============================' fontSize='20'></Label>
32+
</StackLayout>
33+
</TabViewItem.view>
34+
</TabViewItem>
35+
<TabViewItem title="Second Tab">
36+
<TabViewItem.view>
37+
<Label text="Completely different tab!"></Label>
38+
</TabViewItem.view>
39+
</TabViewItem>
40+
</TabView.items>
41+
</TabView>
2942
`,
3043
})
3144
export class RendererTest {

Diff for: ng-sample/tsconfig.json

+36-37
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,38 @@
11
{
2-
"compilerOptions": {
3-
"outDir": "app",
4-
"rootDir": "app",
5-
"module": "commonjs",
6-
"target": "es5",
7-
"inlineSourceMap": true,
8-
"experimentalDecorators": true,
9-
"removeComments": false,
10-
"emitDecoratorMetadata": true,
11-
"noEmitOnError": true
12-
},
13-
"files": [
14-
"app/app.ts",
15-
"app/benchmark.ts",
16-
"app/global.d.ts",
17-
"app/main-page.ts",
18-
"app/main-view-model.ts",
19-
"app/modules.ts",
20-
"app/nativescript-angular/application.d.ts",
21-
"app/nativescript-angular/application.ts",
22-
"app/nativescript-angular/dom_adapter.ts",
23-
"app/nativescript-angular/element-registry.d.ts",
24-
"app/nativescript-angular/element-registry.ts",
25-
"app/nativescript-angular/polyfills/array.ts",
26-
"app/nativescript-angular/renderer.ts",
27-
"app/nativescript-angular/view_node.ts",
28-
"app/nativescript-angular/xhr.ts",
29-
"app/nativescript-angular/zone.ts",
30-
"app/nativescript-angular/zone_patch.ts",
31-
"app/profiling.ts",
32-
"app/renderer-test.ts",
33-
"node_modules/tns-core-modules/tns-core-modules.d.ts"
34-
],
35-
"filesGlob": [
36-
"node_modules/tns-core-modules/tns-core-modules.d.ts",
37-
"app/**/*.ts"
38-
]
2+
"compilerOptions": {
3+
"outDir": "app",
4+
"rootDir": "app",
5+
"module": "commonjs",
6+
"target": "es5",
7+
"inlineSourceMap": true,
8+
"experimentalDecorators": true,
9+
"removeComments": false,
10+
"emitDecoratorMetadata": true,
11+
"noEmitOnError": true
12+
},
13+
"files": [
14+
"app/app.ts",
15+
"app/benchmark.ts",
16+
"app/global.d.ts",
17+
"app/main-page.ts",
18+
"app/main-view-model.ts",
19+
"app/nativescript-angular/application.d.ts",
20+
"app/nativescript-angular/application.ts",
21+
"app/nativescript-angular/dom_adapter.ts",
22+
"app/nativescript-angular/element-registry.d.ts",
23+
"app/nativescript-angular/element-registry.ts",
24+
"app/nativescript-angular/polyfills/array.ts",
25+
"app/nativescript-angular/renderer.ts",
26+
"app/nativescript-angular/view_node.ts",
27+
"app/nativescript-angular/xhr.ts",
28+
"app/nativescript-angular/zone.ts",
29+
"app/nativescript-angular/zone_patch.ts",
30+
"app/profiling.ts",
31+
"app/renderer-test.ts",
32+
"node_modules/tns-core-modules/tns-core-modules.d.ts"
33+
],
34+
"filesGlob": [
35+
"node_modules/tns-core-modules/tns-core-modules.d.ts",
36+
"app/**/*.ts"
37+
]
3938
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ registerElement("Slider", () => require("ui/slider").Slider);
6666
registerElement("StackLayout", () => require("ui/layouts/stack-layout").StackLayout);
6767
registerElement("Switch", () => require("ui/switch").Switch);
6868
registerElement("TabView", () => require("ui/tab-view").TabView);
69+
registerElement("TabViewItem", () => require("ui/tab-view").TabViewItem);
6970
registerElement("TextField", () => require("ui/text-field").TextField);
7071
registerElement("TextView", () => require("ui/text-view").TextView);
7172
registerElement("TimePicker", () => require("ui/time-picker").TimePicker);

Diff for: src/nativescript-angular/view_node.ts

+56-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {Switch} from 'ui/switch';
1313
import {LayoutBase} from 'ui/layouts/layout-base';
1414
import gestures = require("ui/gestures");
1515
import {ViewClass, getViewClass, isKnownView} from './element-registry';
16+
import {isString} from "utils/types";
1617

1718
type EventHandler = (args: EventData) => void;
1819

@@ -28,11 +29,11 @@ export class ViewNode {
2829
private cssClasses: Map<string, boolean> = new Map<string, boolean>();
2930
private static whiteSpaceSplitter = /\s+/;
3031

31-
public children:Array<ViewNode> = [];
32+
public children: Array<ViewNode> = [];
3233

3334
constructor(public parentNode: ViewNode,
34-
public viewName: string,
35-
attrNameAndValues: string[]) {
35+
public viewName: string,
36+
attrNameAndValues: string[]) {
3637
this.setAttributeValues(attrNameAndValues);
3738

3839
if (this.parentNode)
@@ -57,7 +58,7 @@ export class ViewNode {
5758
return this._parentView
5859

5960
if (this.parentNode) {
60-
if(this.parentNode.viewName !== "template" && this.parentNode.nativeView) {
61+
if (this.parentNode.viewName !== "template" && this.parentNode.nativeView) {
6162
this._parentView = this.parentNode.nativeView;
6263
} else {
6364
this._parentView = this.parentNode.parentNativeView;
@@ -69,6 +70,10 @@ export class ViewNode {
6970
return this._parentView;
7071
}
7172

73+
get isComplexProperty(): boolean {
74+
return ViewNode.isComplexProperty(this.viewName);
75+
}
76+
7277
public attachToView(atIndex: number = -1) {
7378
console.log('ViewNode.attachToView ' + this.viewName);
7479
if (this._attachedToView) {
@@ -84,9 +89,11 @@ export class ViewNode {
8489
this.children.forEach(child => {
8590
child.attachToView();
8691
});
92+
93+
this.postAttachUI();
8794
}
8895

89-
private createUI(attachAtIndex: number) {
96+
private createUI(attachAtIndex: number): boolean {
9097
if (!isKnownView(this.viewName))
9198
return;
9299

@@ -118,12 +125,40 @@ export class ViewNode {
118125
}
119126
} else if ((<any>this.parentNativeView)._addChildFromBuilder) {
120127
(<any>this.parentNativeView)._addChildFromBuilder(this.viewName, this.nativeView);
121-
} else {
128+
} else if (this.parentNode.isComplexProperty) {
129+
// complex property - we will deal with this in postAttachUI()
130+
}
131+
else {
122132
console.log('parentNativeView: ' + this.parentNativeView);
123133
throw new Error("Parent view can't have children! " + this.parentNativeView);
124134
}
125135
}
126136

137+
private postAttachUI() {
138+
if (this.isComplexProperty) {
139+
let nativeParent = <any>this.parentNativeView;
140+
if (!nativeParent) {
141+
return;
142+
}
143+
144+
let propertyName = ViewNode.getComplexPropertyName(this.viewName);
145+
let realChildren = [];
146+
for (let child of this.children) {
147+
if (child.nativeView) {
148+
realChildren.push(child.nativeView);
149+
}
150+
}
151+
if (realChildren.length > 0) {
152+
if (nativeParent._addArrayFromBuilder) {
153+
nativeParent._addArrayFromBuilder(propertyName, realChildren);
154+
}
155+
else {
156+
this.parentNode.setAttribute(propertyName, realChildren[0]);
157+
}
158+
}
159+
}
160+
}
161+
127162
private static propertyMaps: Map<Function, Map<string, string>> = new Map<Function, Map<string, string>>();
128163

129164
private static getProperties(instance: any): Map<string, string> {
@@ -142,6 +177,21 @@ export class ViewNode {
142177
return ViewNode.propertyMaps.get(type);
143178
}
144179

180+
private static isComplexProperty(name: string): boolean {
181+
return isString(name) && name.indexOf(".") !== -1;
182+
}
183+
184+
private static getComplexPropertyName(fullName: string): string {
185+
var name: string;
186+
187+
if (isString(fullName)) {
188+
var names = fullName.split(".");
189+
name = names[names.length - 1];
190+
}
191+
192+
return name;
193+
}
194+
145195
private configureUI() {
146196
if (this.attributes.size == 0)
147197
return;
@@ -337,7 +387,6 @@ export class ViewNode {
337387
this.nativeView.cssClass = classValue;
338388
}
339389
}
340-
341390
}
342391

343392
export class DummyViewNode extends ViewNode {

0 commit comments

Comments
 (0)