Skip to content

Commit 5ef0470

Browse files
author
vakrilov
committed
Support setting complex properties - e.x. TabViewItems
1 parent fb2e454 commit 5ef0470

File tree

3 files changed

+85
-21
lines changed

3 files changed

+85
-21
lines changed

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: src/nativescript-angular/element-registry.ts

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ registerElement("Slider", {className: "Slider", moduleName: "ui/slider"});
7070
registerElement("StackLayout", {className: "StackLayout", moduleName: "ui/layouts/stack-layout"});
7171
registerElement("Switch", {className: "Switch", moduleName: "ui/switch"});
7272
registerElement("TabView", {className: "TabView", moduleName: "ui/tab-view"});
73+
registerElement("TabViewItem", {className: "TabViewItem", moduleName: "ui/tab-view"});
7374
registerElement("TextField", {className: "TextField", moduleName: "ui/text-field"});
7475
registerElement("TextView", {className: "TextView", moduleName: "ui/text-view"});
7576
registerElement("TimePicker", {className: "TimePicker", moduleName: "ui/time-picker"});

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

+57-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,41 @@ 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+
162+
127163
private static propertyMaps: Map<Function, Map<string, string>> = new Map<Function, Map<string, string>>();
128164

129165
private static getProperties(instance: any): Map<string, string> {
@@ -142,6 +178,21 @@ export class ViewNode {
142178
return ViewNode.propertyMaps.get(type);
143179
}
144180

181+
private static isComplexProperty(name: string): boolean {
182+
return isString(name) && name.indexOf(".") !== -1;
183+
}
184+
185+
private static getComplexPropertyName(fullName: string): string {
186+
var name: string;
187+
188+
if (isString(fullName)) {
189+
var names = fullName.split(".");
190+
name = names[names.length - 1];
191+
}
192+
193+
return name;
194+
}
195+
145196
private configureUI() {
146197
if (this.attributes.size == 0)
147198
return;
@@ -337,7 +388,6 @@ export class ViewNode {
337388
this.nativeView.cssClass = classValue;
338389
}
339390
}
340-
341391
}
342392

343393
export class DummyViewNode extends ViewNode {

0 commit comments

Comments
 (0)