diff --git a/ng-sample/app/app.css b/ng-sample/app/app.css
index 17e1cb37f..100bc6a6f 100644
--- a/ng-sample/app/app.css
+++ b/ng-sample/app/app.css
@@ -17,3 +17,11 @@ button {
font-size: 42;
horizontal-align: center;
}
+
+.odd {
+ background-color: hotpink
+}
+
+.even {
+ background-color: lightseagreen;
+}
\ No newline at end of file
diff --git a/ng-sample/app/list-test.ts b/ng-sample/app/list-test.ts
new file mode 100644
index 000000000..c7824c411
--- /dev/null
+++ b/ng-sample/app/list-test.ts
@@ -0,0 +1,75 @@
+import {Component, Input} from 'angular2/core';
+
+class DataItem {
+ constructor(public id: number, public name: string) { }
+}
+
+@Component({
+ selector: 'item-component',
+ template: `
+
+
+
+
+ `
+})
+export class ItemComponent {
+ @Input() data: DataItem;
+ @Input() odd: boolean;
+ @Input() even: boolean;
+ constructor() { }
+}
+
+@Component({
+ selector: 'list-test',
+ directives: [ItemComponent],
+ template: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+ // TEMPLATE WITH COMPONENT
+ //
+ //
+ //
+
+ // IN-PLACE TEMPLATE
+ //
+ //
+ //
+ //
+ //
+ //
+})
+export class ListTest {
+ public myItems: Array;
+
+ constructor() {
+ this.myItems = [];
+ for (var i = 0; i < 30; i++) {
+ this.myItems.push(new DataItem(i, "data item " + i));
+ }
+ }
+
+ public onItemTap(args) {
+ console.log("------------------------ ItemTapped: " + args.index);
+ }
+}
+
diff --git a/ng-sample/app/main-page.ts b/ng-sample/app/main-page.ts
index 892f5eb06..545c1ce19 100644
--- a/ng-sample/app/main-page.ts
+++ b/ng-sample/app/main-page.ts
@@ -4,8 +4,9 @@ import {TextView} from 'ui/text-view';
import {Page} from 'ui/page';
import {nativeScriptBootstrap} from './nativescript-angular/application';
-import {RendererTest} from './renderer-test';
+// import {RendererTest} from './renderer-test';
//import {Benchmark} from './benchmark';
+import {ListTest} from './list-test';
export function createPage() {
var page = new Page();
@@ -17,7 +18,8 @@ export function createPage() {
profiling.start('ng-bootstrap');
console.log('BOOTSTRAPPING...');
//nativeScriptBootstrap(Benchmark, []).then((appRef) => {
- nativeScriptBootstrap(RendererTest, []).then((appRef) => {
+ // nativeScriptBootstrap(RendererTest, []).then((appRef) => {
+ nativeScriptBootstrap(ListTest, []).then((appRef) => {
profiling.stop('ng-bootstrap');
console.log('ANGULAR BOOTSTRAP DONE.');
}, (err) =>{
diff --git a/ng-sample/references.d.ts b/ng-sample/references.d.ts
new file mode 100644
index 000000000..b14f3837d
--- /dev/null
+++ b/ng-sample/references.d.ts
@@ -0,0 +1 @@
+/// Needed for autocompletion and compilation.
\ No newline at end of file
diff --git a/ng-sample/tsconfig.json b/ng-sample/tsconfig.json
index f3b8d24ad..261a73583 100644
--- a/ng-sample/tsconfig.json
+++ b/ng-sample/tsconfig.json
@@ -10,30 +10,12 @@
"emitDecoratorMetadata": true,
"noEmitOnError": true
},
- "files": [
- "app/app.ts",
- "app/benchmark.ts",
- "app/global.d.ts",
- "app/main-page.ts",
- "app/main-view-model.ts",
- "app/nativescript-angular/application.d.ts",
- "app/nativescript-angular/application.ts",
- "app/nativescript-angular/dom_adapter.ts",
- "app/nativescript-angular/element-registry.d.ts",
- "app/nativescript-angular/element-registry.ts",
- "app/nativescript-angular/polyfills/array.ts",
- "app/nativescript-angular/renderer.ts",
- "app/nativescript-angular/view_node.ts",
- "app/nativescript-angular/xhr.ts",
- "app/nativescript-angular/zone.ts",
- "app/nativescript-angular/zone_patch.ts",
- "app/profiling.ts",
- "app/renderer-test.ts",
- "app/starter.ts",
- "node_modules/tns-core-modules/tns-core-modules.d.ts"
- ],
"filesGlob": [
"node_modules/tns-core-modules/tns-core-modules.d.ts",
"app/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules",
+ "platforms"
]
}
\ No newline at end of file
diff --git a/src/nativescript-angular/application.ts b/src/nativescript-angular/application.ts
index 293a566d0..73281b687 100644
--- a/src/nativescript-angular/application.ts
+++ b/src/nativescript-angular/application.ts
@@ -24,6 +24,7 @@ import {APPLICATION_COMMON_PROVIDERS} from 'angular2/src/core/application_common
import {COMPILER_PROVIDERS} from 'angular2/src/compiler/compiler';
import {PLATFORM_COMMON_PROVIDERS} from 'angular2/src/core/platform_common_providers';
import {COMMON_DIRECTIVES, COMMON_PIPES, FORM_PROVIDERS} from "angular2/common";
+import {NS_DIRECTIVES} from './directives/ns-directives';
import {bootstrap as angularBootstrap} from 'angular2/bootstrap';
@@ -41,6 +42,7 @@ export function nativeScriptBootstrap(appComponentType: any,
provide(PLATFORM_PIPES, {useValue: COMMON_PIPES, multi: true}),
provide(PLATFORM_DIRECTIVES, {useValue: COMMON_DIRECTIVES, multi: true}),
+ provide(PLATFORM_DIRECTIVES, {useValue: NS_DIRECTIVES, multi: true}),
APPLICATION_COMMON_PROVIDERS,
COMPILER_PROVIDERS,
diff --git a/src/nativescript-angular/directives/list-view.ts b/src/nativescript-angular/directives/list-view.ts
new file mode 100644
index 000000000..7beaf2984
--- /dev/null
+++ b/src/nativescript-angular/directives/list-view.ts
@@ -0,0 +1,90 @@
+import {HostListener, Host, Directive, Component, ContentChild, ViewRef, TemplateRef, ViewContainerRef} from 'angular2/core';
+import {View} from 'ui';
+import {ViewNode, DummyViewNode} from '../view_node';
+
+const NG_VIEW = "_ngViewRef";
+
+@Directive({
+ selector: 'ListView',
+})
+export class ListViewDirective {
+ private itemTemplate: ListItemTemplate;
+ public registerItemTemplate(container: ListItemTemplate) {
+ this.itemTemplate = container;
+ }
+
+ @HostListener("itemLoading", ['$event'])
+ public onItemLoading(args) {
+ if (!this.itemTemplate) {
+ return;
+ }
+
+ let index = args.index;
+ let items = args.object.items;
+ let currentItem = typeof (items.getItem) === "function" ? items.getItem(index) : items[index];
+ let viewRef: ViewRef;
+
+ if (args.view) {
+ console.log("ListView.onItemLoading: " + index + " - Reusing exisiting view");
+ viewRef = args.view[NG_VIEW];
+ }
+ else {
+ console.log("ListView.onItemLoading: " + index + " - Creating view from template");
+ viewRef = this.itemTemplate.instantiateTemplate();
+ args.view = getSingleViewFromViewRef(viewRef);
+ args.view[NG_VIEW] = viewRef;
+ }
+ this.setupViewRef(viewRef, currentItem, index);
+ }
+
+ public setupViewRef(viewRef: ViewRef, data: any, index: number): void {
+ viewRef.setLocal('\$implicit', data.item);
+ viewRef.setLocal("item", data);
+ viewRef.setLocal("index", index);
+ viewRef.setLocal('even', (index % 2 == 0));
+ viewRef.setLocal('odd', (index % 2 == 1));
+ }
+}
+
+@Component({
+ selector: 'item-template',
+ template: ``,
+})
+export class ListItemTemplate {
+ @ContentChild(TemplateRef) template: TemplateRef;
+
+ constructor(
+ @Host() listDirective: ListViewDirective,
+ private _viewContainer: ViewContainerRef) {
+
+ listDirective.registerItemTemplate(this);
+ }
+
+ public instantiateTemplate(): ViewRef {
+ return this._viewContainer.createEmbeddedView(this.template);
+ }
+}
+
+function getSingleViewFromViewRef(viewRef: ViewRef): View {
+ // Hacky Hacky Hacky !!!
+ var getSingleViewRecursive = (nodes: Array, nestLevel: number) => {
+ var actualNodes = nodes.filter((n) => !(n instanceof DummyViewNode));
+
+ if (actualNodes.length === 0) {
+ throw new Error("No suitable views found in list template! Nesting level: " + nestLevel);
+ }
+ else if (actualNodes.length > 1) {
+ throw new Error("More than one view found in list template! Nesting level: " + nestLevel);
+ }
+ else {
+ if (actualNodes[0].nativeView) {
+ return actualNodes[0].nativeView;
+ }
+ else {
+ return getSingleViewRecursive(actualNodes[0].children, nestLevel + 1)
+ }
+ }
+ }
+
+ return getSingleViewRecursive((viewRef).renderFragment.nodes, 0);
+}
\ No newline at end of file
diff --git a/src/nativescript-angular/directives/ns-directives.ts b/src/nativescript-angular/directives/ns-directives.ts
new file mode 100644
index 000000000..fb58f7417
--- /dev/null
+++ b/src/nativescript-angular/directives/ns-directives.ts
@@ -0,0 +1,4 @@
+import {Type} from 'angular2/src/facade/lang';
+import {ListItemTemplate, ListViewDirective} from './list-view';
+
+export const NS_DIRECTIVES: Type[] = [ListItemTemplate, ListViewDirective];
diff --git a/src/nativescript-angular/view_node.ts b/src/nativescript-angular/view_node.ts
index 1e53f0faa..a32089bec 100644
--- a/src/nativescript-angular/view_node.ts
+++ b/src/nativescript-angular/view_node.ts
@@ -131,8 +131,8 @@ export class ViewNode {
// complex property - we will deal with this in postAttachUI()
}
else {
- console.log('parentNativeView: ' + this.parentNativeView);
- throw new Error("Parent view can't have children! " + this.parentNativeView);
+ // Child adding will be handled elsewhere. For example ListView
+ console.log('Child not added for parent. child: ' + this.viewName + ', parent: ' + this.parentNativeView);
}
}