Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ src/nativescript-angular/**/*.js
.baseDir.ts
.tscache
.nvm
.vscode

tests/app/**/*.js
tests/app/global.d.ts
Expand Down
4 changes: 2 additions & 2 deletions ng-sample/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import {ImageTest} from "./examples/image/image-test";
import {NavigationTest} from "./examples/navigation/navigation-test";


nativeScriptBootstrap(RendererTest);
//nativeScriptBootstrap(RendererTest);
//nativeScriptBootstrap(Benchmark);
//nativeScriptBootstrap(ListTest);
// nativeScriptBootstrap(ListTestAsync);
nativeScriptBootstrap(ListTestAsync);
// nativeScriptBootstrap(ImageTest);
//nativeScriptBootstrap(NavigationTest, [NS_ROUTER_PROVIDERS]);
23 changes: 11 additions & 12 deletions ng-sample/app/examples/list/list-test-async.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Component, Input, ChangeDetectionStrategy } from 'angular2/core';
import { Observable as RxObservable } from 'rxjs/Observable';
import { Observable, WrappedValue } from 'data/observable';

class DataItem {
constructor(public id: number, public name: string) { }
Expand All @@ -10,15 +9,15 @@ class DataItem {
selector: 'list-test-async',
styleUrls: ['examples/list/list-test-async.css'],
template: `
<ListView [items]="myItems | async" (itemTap)="onItemTap($event)">
<item-template>
<template #item="item" #i="index" #odd="odd" #even="even">
<StackLayout [class.odd]="odd" [class.even]="even">
<Label class="test" [text]='"index: " + item.name'></Label>
</StackLayout>
</template>
</item-template>
</ListView>
<GridLayout>
<ListView [items]="myItems | async" (itemTap)="onItemTap($event)">
<template #item="item" #i="index" #odd="odd" #even="even">
<StackLayout [class.odd]="odd" [class.even]="even">
<Label class="test" [text]='"index: " + item.name'></Label>
</StackLayout>
</template>
</ListView>
</GridLayout>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
Expand All @@ -34,7 +33,7 @@ export class ListTestAsync {
var subscr;
this.myItems = RxObservable.create(subscriber => {
subscr = subscriber;
subscriber.next(WrappedValue.wrap(items));
subscriber.next(items);
return function () {
console.log("Unsubscribe called!!!");
}
Expand All @@ -45,7 +44,7 @@ export class ListTestAsync {
counter++;
console.log("Adding " + counter + "-th item");
items.push(new DataItem(counter, "data item " + counter));
subscr.next(WrappedValue.wrap(items));
subscr.next(items);
}, 1000);

setTimeout(() => {
Expand Down
79 changes: 50 additions & 29 deletions ng-sample/app/examples/list/list-test.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,51 @@
import {Component, Input} from 'angular2/core';
import {Component, Input, WrappedValue, ChangeDetectionStrategy} from 'angular2/core';
import {Label} from 'ui/label';
import {ObservableArray} from 'data/observable-array';

class DataItem {
constructor(public id: number, public name: string) { }
}

@Component({
selector: 'item-component',
template: `
<StackLayout [class.odd]="odd" [class.even]="even">
<Label [text]='"id: " + data.id'></Label>
<Label [text]='"name: " + data.name'></Label>
</StackLayout>
`
})
export class ItemComponent {
@Input() data: DataItem;
@Input() odd: boolean;
@Input() even: boolean;
constructor() { }
}
// @Component({
// selector: 'item-component',
// template: `
// <StackLayout [class.odd]="odd" [class.even]="even">
// <Label [text]='"id: " + data.id'></Label>
// <Label [text]='"name: " + data.name'></Label>
// </StackLayout>
// `
// })
// export class ItemComponent {
// @Input() data: DataItem;
// @Input() odd: boolean;
// @Input() even: boolean;
// constructor() { }
// }

@Component({
selector: 'list-test',
directives: [ItemComponent],
//directives: [ItemComponent],
template: `
<GridLayout rows="auto, *, auto">
<GridLayout rows="auto, *, auto, auto">
<Label row="0" text="-==START==-" fontSize="20"></Label>
<GridLayout row="1">
<ListView [items]="myItems" (itemTap)="onItemTap($event)">
<item-template>
<template #item="item" #i="index" #odd="odd" #even="even">
<StackLayout [class.odd]="odd" [class.even]="even">
<Label [text]='"index: " + i'></Label>
<Label [text]='"[" + item.id +"] " + item.name'></Label>
</StackLayout>
</template>
</item-template>
<template #item="item" #i="index" #odd="odd" #even="even">
<StackLayout [class.odd]="odd" [class.even]="even">
<Label [text]='"index: " + i'></Label>
<Label [text]='"[" + item.id +"] " + item.name'></Label>
</StackLayout>
</template>
</ListView>
</GridLayout>
<Label row="2" text="-==END==-" fontSize="20"></Label>
<Label row="2" id="testLabel" text="-==END==-" fontSize="20"></Label>
<StackLayout row="3">
<Button text="test" (tap)="onButtonTap()" ></Button>
<Button text="second test" (tap)="onSecondButtonTap($event)" ></Button>
</StackLayout>
</GridLayout>
`
`,
changeDetection: ChangeDetectionStrategy.OnPush
// TEMPLATE WITH COMPONENT
// <template #item="item" #i="index" #odd="odd" #even="even">
// <item-component [data]="item" [odd]='odd' [even]='even'></item-component>
Expand All @@ -55,17 +60,33 @@ export class ItemComponent {
// </template>
})
export class ListTest {
//public myItems: ObservableArray<DataItem>;
public myItems: Array<DataItem>;
private counter: number;

constructor() {
//this.myItems = new ObservableArray<DataItem>();
this.myItems = [];
for (var i = 0; i < 30; i++) {
this.counter = 0;
for (var i = 0; i < 50; i++) {
this.myItems.push(new DataItem(i, "data item " + i));
this.counter = i;
}
}

public onItemTap(args) {
console.log("------------------------ ItemTapped: " + args.index);
}

onButtonTap() {
this.counter++;
this.myItems.push(new DataItem(this.counter, "data item " + this.counter));
}

onSecondButtonTap(args) {
var page = args.object.page;
var label = <Label>page.getViewById("testLabel");
label.text = "Alabala";
}
}

129 changes: 129 additions & 0 deletions src/nativescript-angular/directives/list-view-comp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import {
Component,
DoCheck,
ElementRef,
TemplateRef,
ContentChild,
AppViewManager,
EmbeddedViewRef,
HostListener,
IterableDiffers,
IterableDiffer,
ChangeDetectorRef} from 'angular2/core';
import {Observable as RxObservable} from 'rxjs'
import {ListView} from 'ui/list-view';
import {View} from 'ui/core/view';
import {NgView} from '../view-util';
import {ObservableArray} from 'data/observable-array';
import {LayoutBase} from 'ui/layouts/layout-base';
const NG_VIEW = "_ngViewRef";

@Component({
selector: 'ListView',
template: ``,
inputs: ['items']
})
export class ListViewComponent {
private listView: ListView;
private _items: any;
private _differ: IterableDiffer;

@ContentChild(TemplateRef) itemTemplate: TemplateRef;

set items(value: any) {
this._items = value;
var needDiffer = true;
if (value instanceof ObservableArray) {
needDiffer = false;
}
if (needDiffer && !this._differ && value) {
this._differ = this._iterableDiffers.find(this._items).create(this._cdr, (index, item) => { return item;});
}
this.listView.items = this._items;
}

private timerId: number;
private doCheckDelay = 5;

constructor(private _elementRef: ElementRef,
private _iterableDiffers: IterableDiffers,
private _cdr: ChangeDetectorRef,
private _appViewManager: AppViewManager) {
this.listView = _elementRef.nativeElement;
}

@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: EmbeddedViewRef;

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._appViewManager.createEmbeddedViewInContainer(this._elementRef, index, this.itemTemplate);
args.view = getSingleViewFromViewRef(viewRef);
args.view[NG_VIEW] = viewRef;
}
this.setupViewRef(viewRef, currentItem, index);
}

public setupViewRef(viewRef: EmbeddedViewRef, 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));
}

ngDoCheck() {
if (this.timerId) {
clearTimeout(this.timerId);
}

this.timerId = setTimeout(() => {
clearTimeout(this.timerId);
if (this._differ) {
var changes = this._differ.diff(this._items);
if (changes) {
this.listView.refresh();
}
}
}, this.doCheckDelay);
}
}

function getSingleViewFromViewRef(viewRef: EmbeddedViewRef): View {
var getSingleViewRecursive = (nodes: Array<any>, nestLevel: number) => {
var actualNodes = nodes.filter((n) => !!n && n.nodeName !== "#text");

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]) {
let parentLayout = actualNodes[0].parent;
if (parentLayout instanceof LayoutBase) {
parentLayout.removeChild(actualNodes[0]);
}
return actualNodes[0];
}
else {
return getSingleViewRecursive(actualNodes[0].children, nestLevel + 1)
}
}
}

return getSingleViewRecursive(viewRef.rootNodes, 0);
}
Loading