I was looking for some optimisation in my app then i stumble uppon something weird. In my template i've done this:
<ion-content>
<ion-list [virtualScroll]="storeStands.collection$ | async"
[virtualTrackBy]="trackStand"
[headerFn]="alphabetical" >
<ion-item-divider *virtualHeader="let header">{{ header }}</ion-item-divider>
<a ion-item text-wrap
*virtualItem="let stand"
[navPush]="[standPage, { stand: stand }]">
<h2>{{ stand.organization }}</h2>
</a>
</ion-list>
</ion-content>
In my controller
trackStand(index, stand: Stand) {
console.log(index, stand);
return stand.id;
}
Putting a console log in trackStand
function but it's never called (as opposed with ngForTrackBy).
Explorating futher i put a console.log(val)
inside the ionic-angular/components/virtual-scroll/virtual-scroll.js:305
to see if my parameter was listened, and i get undefined
.
set: function (val) {
this._trackBy = val;
}
Moving back to my template i set [virtualTrackBy]="'trackStand'"
and i then get 'trackStand'
inside virtual-scroll.js:306
.
But was more curious an tracked where this._trackBy
was used, in the same file virtual-scroll.js:260
inside a condition.
set: function (val) {
this._records = val;
if (util_1.isBlank(this._differ) && util_1.isPresent(val)) {
this._differ = this._iterableDiffers.find(val).create(this._cd, this._trackBy);
}
}
I put console.log(this._trackBy, this._differ)
inside that condition and surprise, this._trackBy
is undefined and this._differ
has a method _trackByFn
with attribute name: 'trackByIdentity'
.
Putting the console.log
just before the condition, the this._trackBy
display two times, one with undefined
and one with 'trackStand'
, this._differ
doesn't change at all.
A final test was to remove the condition if (util_1.isBlank(this._differ) && util_1.isPresent(val))
and there this._differ._trackByFn.name
was empty when [virtualTrackBy]="trackStand"
and only there it work as expected.
So my conclusion is, when this._differ
is set, and even if val
change, this._differ
isn't changed, and doesn't take in account this._trackBy
.
Or maybe it's me who use it badly ?
Hello, thanks for opening an issue with us! Would you be able to provide a plunker that demonstrates this issue? Thanks for using Ionic!
Here's a demo http://plnkr.co/edit/yWbcNoSAFlxeOPVIRbqF?p=preview
+1
Any update about this issue?
I have the same problem with ionic 2.0.0 RC4,
[virtualTrackBy]="trackStand" does not execute,
if (util_1.isBlank(this._differ) && util_1.isPresent(val)) condition it's alway false.
I am also having this problem. I am using an ion-searchbar to filter down my ion-list but when there are hundreds of records that get regenerated, the phone runs very poorly.
Just came across this issue as well. Added virtualTrackBy with a console.log statement in the function it uses and it never gets called. Seems like virtualTrackBy is not working at all.
@jgw96 - this would be great to get fixed before 2.0 final as it is a function listed in the documentation , and an important function for list performance that just does not work currently.
I am also having the same problem, same as above, added a console.log in the function and nothing gets called.
Agreed, @ghenry22. Virtual scrolling is a must for big lists but DOM rewrites are too expensive to not have this functionality. A decent example in the Ionic docs would be very useful. Interestingly, if you go to:
node_modules/ionic-angular/components/virtual-scroll/virtual-scroll.js
, there is no Object.defineProperty(VirtualScroll.prototype, "virtualTrackBy", {})
as with headerFn
and footerFn
and as one might expect.
@jgw96 - is it too late for this issue? It would be great if this could be slipped into final.
Just upgraded to 2.0.0, was excited to try virtualScroll in place of ngFor, but virtualTrackBy is never called.
I don't know if it work for anyone yet, but it work normal for me .
Here is the html
<ion-content padding>
<ion-list [virtualScroll]="noidungs | async" no-lines [virtualTrackBy]="identify">
<div *virtualItem="let nd" style="width: 100%">
<ion-card>
<ion-card-header>
{{nd.name}}
</ion-card-header>
<ion-card-content>
{{nd.message}}
</ion-card-content>
</ion-card>
<div style="height:10px"></div>
</div>
</ion-list>
</ion-content>
And here is controller
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { NoiDungService } from '../../shared/noi-dung.service';
@Component({
selector: 'page-list',
templateUrl: 'list.html'
})
export class ListPage {
private noidungs;
constructor(public navCtrl: NavController,
public navParams: NavParams,
private noiDungService: NoiDungService) { }
ionViewDidLoad() {
console.log('ionViewDidLoad ListPage');
this.getNoidungs();
}
public getNoidungs() {
this.noidungs = this.noiDungService.getDataFromServer();
}
public identify(index, item) {
console.log('helo world');
return item.name;
}
}
Here is the output of ionic info
Cordova CLI: 6.4.0
Ionic CLI Version: 2.2.1
Ionic App Lib Version: 2.2.0
ios-deploy version: Not installed
ios-sim version: Not installed
OS: Linux 3.16
Node Version: v6.9.1
Xcode version: Not installed
Hope that help :smile:
If you add a console.log statement in your method that virtualtrackby is supposed to call you will see that it never gets called. The list will still display and all looks normal but the track by function is not used so you don't get the benefits of it.
@ghenry22 yes i know, but in my code the console.log('helo world')
is run, so the identify
is called by virtualTrackBy
Any updates?
Fixed by @masimplo!!
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.
Most helpful comment
Any update about this issue?
I have the same problem with ionic 2.0.0 RC4,
[virtualTrackBy]="trackStand" does not execute,
if (util_1.isBlank(this._differ) && util_1.isPresent(val)) condition it's alway false.