Reputation: 43
I am trying to load a large list of elements (~630 elements) in an ionic application. I am particularly interested in optimizing the time it takes to initially load the page.
I have tried using virtual scroll as to only load the elements on-demand. This works great as my page loads quick and there is no delay trying to load all 630 elements before the page is rendered. Instead, only items in the viewport are rendered which results in a smooth UX.
My problem is this:
I am using a search bar to filter the list and my implementation requires all items be loaded in the DOM to properly filter. By using virtual scroll, my filter doesn't work properly as items are not inserted into the DOM unless they are in the viewport.
I would like to be able to have a page that loads quickly but that also can be filtered. Is there an alternative to virtual scroll that I can use to initially load my page faster? Or should I change my filter implementation?
Here is my code:
home.html
<ion-searchbar (ionInput)="onSearch($event)" class="hymns-searchbar" placeholder="Search" [showCancelButton]="shouldShowCancel" (ionCancel)="onClear()"></ion-searchbar>
...
<ion-content padding>
<ion-list [virtualScroll]="hymns">
<div *virtualItem="let song; let i = index;"
id="songItems" approxItemHeight="62px" bufferRatio="10">
<button ion-item clear class="hymns-list-item"
[navPush]="songPage" [navParams]=song>
<h4 class="song-title">
<span class="song-number">{{i + 1}}</span>{{ song.title }}
</h4>
<small class="song-genre">{{song.category}}</small>
</button>
</div>
</ion-list>
</ion-content>
home.ts
public hymns: any;
private songItems:any;
ngOnInit() {
this.hymns = songs; // Array with 630 elements
}
onSearch(event) {
let val = event.target.value;
if (typeof val == 'undefined') {
// clear list
}
else {
val = val.toUpperCase();
this.songItems = document.querySelectorAll('#songItems');
for (let i = 0; i < this.hymns.length; i++) {
let title = this.hymns[i].title;
if (title.toUpperCase().indexOf(val) > -1) {
this.songItems[i].style.display = '';
}
else {
this.songItems[i].style.display = 'none';
}
}
}
Upvotes: 1
Views: 2753
Reputation: 1088
Virtual scrolling is a good optimization mechanism. You should leave it.
It's better to not interact directly with the DOM. Angular gives you a great abstraction over the DOM. You can try to optimize your search by having a separate array for displaying filtered values.
template
<ion-searchbar (ionInput)="onSearch($event)"></ion-searchbar>
<ion-list [virtualScroll]="displaySongs">
<ion-item *virtualItem="let item">
{{ item }}
</ion-item>
</ion-list>
ts
public displaySongs: [];
private allSongs: [];
ngOnInit() {
this.allSongs = songs; // Array with 630 elements
this.displaySongs = songs;
}
onSearch(event) {
const searchQuery = event.target.value.toUpperCase();
this.displaySongs = this.allSongs
.filter((song) => song.toUpperCase().includes(searchQuery));
}
Upvotes: 2