Skip to content

Commit 2b36449

Browse files
author
vakrilov
committed
Fix: Cyclic change detection when list view is present
1 parent 2530918 commit 2b36449

File tree

2 files changed

+45
-35
lines changed

2 files changed

+45
-35
lines changed

nativescript-angular/directives/list-view-comp.ts

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import {
2-
Component,
3-
DoCheck,
4-
ElementRef,
2+
Component,
3+
DoCheck,
4+
ElementRef,
55
ViewContainerRef,
6-
TemplateRef,
7-
ContentChild,
6+
TemplateRef,
7+
ContentChild,
88
EmbeddedViewRef,
9-
HostListener,
10-
IterableDiffers,
9+
HostListener,
10+
IterableDiffers,
1111
IterableDiffer,
1212
ChangeDetectorRef,
1313
EventEmitter,
1414
ViewChild,
1515
Output,
16+
NgZone,
1617
ChangeDetectionStrategy} from '@angular/core';
1718
import {isBlank} from '@angular/core/src/facade/lang';
1819
import {isListLikeIterable} from '@angular/core/src/facade/collection';
@@ -55,11 +56,11 @@ export class ListViewComponent {
5556
public get nativeElement(): ListView {
5657
return this.listView;
5758
}
58-
59+
5960
private listView: ListView;
6061
private _items: any;
6162
private _differ: IterableDiffer;
62-
63+
6364
@ViewChild('loader', { read: ViewContainerRef }) loader: ViewContainerRef;
6465

6566
@Output() public setupItemView: EventEmitter<SetupItemViewArgs> = new EventEmitter<SetupItemViewArgs>();
@@ -73,17 +74,18 @@ export class ListViewComponent {
7374
needDiffer = false;
7475
}
7576
if (needDiffer && !this._differ && isListLikeIterable(value)) {
76-
this._differ = this._iterableDiffers.find(this._items).create(this._cdr, (index, item) => { return item;});
77+
this._differ = this._iterableDiffers.find(this._items).create(this._cdr, (index, item) => { return item; });
7778
}
7879
this.listView.items = this._items;
7980
}
8081

8182
private timerId: number;
8283
private doCheckDelay = 5;
83-
84+
8485
constructor(private _elementRef: ElementRef,
85-
private _iterableDiffers: IterableDiffers,
86-
private _cdr: ChangeDetectorRef) {
86+
private _iterableDiffers: IterableDiffers,
87+
private _cdr: ChangeDetectorRef,
88+
private _zone: NgZone) {
8789
this.listView = _elementRef.nativeElement;
8890
}
8991

@@ -126,23 +128,25 @@ export class ListViewComponent {
126128
context.even = (index % 2 == 0);
127129
context.odd = !context.even;
128130

129-
this.setupItemView.next({view: viewRef, data: data, index: index, context: context});
131+
this.setupItemView.next({ view: viewRef, data: data, index: index, context: context });
130132
}
131133

132134
ngDoCheck() {
133135
if (this.timerId) {
134136
clearTimeout(this.timerId);
135137
}
136138

137-
this.timerId = setTimeout(() => {
138-
clearTimeout(this.timerId);
139-
if (this._differ) {
140-
var changes = this._differ.diff(this._items);
141-
if (changes) {
142-
this.listView.refresh();
139+
this._zone.runOutsideAngular(() => {
140+
this.timerId = setTimeout(() => {
141+
clearTimeout(this.timerId);
142+
if (this._differ) {
143+
var changes = this._differ.diff(this._items);
144+
if (changes) {
145+
this.listView.refresh();
146+
}
143147
}
144-
}
145-
}, this.doCheckDelay);
148+
}, this.doCheckDelay);
149+
});
146150
}
147151
}
148152

ng-sample/app/examples/list/list-test.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, Input, WrappedValue, ChangeDetectionStrategy} from '@angular/core';
1+
import {Component, Input, WrappedValue, ChangeDetectionStrategy, AfterViewChecked, DoCheck} from '@angular/core';
22
import {Label} from 'ui/label';
33
import {ObservableArray} from 'data/observable-array';
44

@@ -8,24 +8,34 @@ class DataItem {
88

99
@Component({
1010
selector: 'item-component',
11-
styleUrls: ['examples/list/styles.css'],
11+
styleUrls: ['examples/list/styles.css'],
12+
// changeDetection: ChangeDetectionStrategy.OnPush,
1213
template: `
1314
<StackLayout [class.odd]="odd" [class.even]="even">
14-
<Label [text]='"[" + data.id + "]name: " + data.name'></Label>
15+
<Label [text]='"[" + data.id + "]:" + data.name'></Label>
1516
</StackLayout>
1617
`
1718
})
18-
export class ItemComponent {
19+
export class ItemComponent implements AfterViewChecked,DoCheck {
1920
@Input() data: DataItem;
2021
@Input() odd: boolean;
2122
@Input() even: boolean;
2223
constructor() { }
24+
25+
ngDoCheck(){
26+
// console.log("ItemComponent.ngDoCheck: " + this.data.id);
27+
}
28+
29+
ngAfterViewChecked(){
30+
// console.log("ItemComponent.ngAfterViewChecked: " + this.data.id);
31+
}
2332
}
2433

2534
@Component({
2635
selector: 'list-test',
2736
styleUrls: ['examples/list/styles.css'],
2837
directives: [ItemComponent],
38+
// changeDetection: ChangeDetectionStrategy.OnPush,
2939
template: `
3040
<GridLayout rows="auto * auto" columns="* *">
3141
<Label text="ListView" class="list-title"></Label>
@@ -36,7 +46,6 @@ export class ItemComponent {
3646
<item-component [data]="item" [odd]="odd" [even]="even"></item-component>
3747
</template>
3848
</ListView>
39-
4049
<StackLayout row="1" col="1" margin="10">
4150
<StackLayout *ngFor="let item of myItems; let odd = odd; let even = even"
4251
[class.odd]="odd" [class.even]="even" marginBottom="1">
@@ -46,11 +55,10 @@ export class ItemComponent {
4655
4756
<StackLayout row="2" colspan="2" orientation="horizontal">
4857
<Button text="add item" (tap)="addItem()" ></Button>
49-
<Button text="second test" (tap)="onSecondButtonTap($event)" ></Button>
58+
<Button text="tap" (tap)="justTap()" ></Button>
5059
</StackLayout>
5160
</GridLayout>
52-
`,
53-
changeDetection: ChangeDetectionStrategy.OnPush
61+
`
5462
// TEMPLATE WITH COMPONENT
5563
// <template let-item="item" let-i="index" let-odd="odd" let-even="even">
5664
// <item-component [data]="item" [odd]='odd' [even]='even'></item-component>
@@ -73,7 +81,7 @@ export class ListTest {
7381
//this.myItems = new ObservableArray<DataItem>();
7482
this.myItems = [];
7583
this.counter = 0;
76-
for (var i = 0; i < 10; i++) {
84+
for (var i = 0; i < 2; i++) {
7785
this.myItems.push(new DataItem(i, "data item " + i));
7886
this.counter = i;
7987
}
@@ -88,9 +96,7 @@ export class ListTest {
8896
this.myItems.push(new DataItem(this.counter, "data item " + this.counter));
8997
}
9098

91-
onSecondButtonTap(args) {
92-
var page = args.object.page;
93-
var label = <Label>page.getViewById("testLabel");
94-
label.text = "Alabala";
99+
justTap() {
100+
console.log("----------------- TAP -----------------");
95101
}
96102
}

0 commit comments

Comments
 (0)