Listview
Using a ListView control inside Angular app requires some special attention due to the complexity of the NativeScript ListView control, with custom item templates, bindings and so on.
The NativeScript-angular plugin provides a custom Angular component which simplifies the way native ListView is used.
Note: Using the
ListViewcomponent inside aScrollVieworScrollViewinside theListView's items can lead to a poor user interface performance and can reflect the user experience. For avoiding those issues, we should specify the height explicitly for the ListView in the scenario when the ListView is nested inScrollViewand theScrollView's height - when the component is used inside theListView. Example 1 (ListViewinScrollView):<ScrollView> <StackLayout> <ListView height="150" [items]="countries"> <ng-template let-country="item" let-i="index" let-odd="odd" let-even="even"> <!-- ....... --> </ng-template> </ListView> </StackLayout> </ScrollView>Example 2 (
ScrollViewinListView):<ListView [items]="countries"> <ng-template let-country="item" let-i="index" let-odd="odd" let-even="even"> <StackLayout> <ScrollView height="150" > <!-- ....... --> </ScrollView> </StackLayout> </ng-template> </ListView>
Usage
<ListView [items]="items" (itemTap)="onItemTap($event)" class="list-group">
<ng-template let-item="item" let-i="index" let-odd="odd" let-even="even">
<!-- The item template can only have a single root view container (e.g. GridLayout, StackLayout, etc.)-->
<GridLayout>
<Label [text]="item.name" class="list-group-item"></Label>
</GridLayout>
</ng-template>
</ListView>
import { Component, OnInit } from "@angular/core";
import { ItemService, Item } from "./usage.service";
import { ItemEventData } from "tns-core-modules/ui/list-view";
@Component({
moduleId: module.id,
templateUrl: "./usage.component.html"
})
export class ListViewUsageComponent implements OnInit {
items: Array<Item>;
constructor(private _itemService: ItemService) { }
ngOnInit(): void {
this.items = this._itemService.getItems();
}
onItemTap(args: ItemEventData) {
console.log(`Index: ${args.index}; View: ${args.view} ; Item: ${this.items[args.index]}`);
}
}
import { Injectable } from "@angular/core";
import { ListViewExamplesModule } from "../listview-examples.module";
@Injectable({
providedIn: "root"
})
export class ItemService {
private items = new Array<Item>(
{ id: 1, name: "Ter Stegen", role: "Goalkeeper" },
{ id: 3, name: "Piqué", role: "Defender" },
{ id: 4, name: "I. Rakitic", role: "Midfielder" },
{ id: 5, name: "Sergio", role: "Midfielder" },
{ id: 6, name: "Denis Suárez", role: "Midfielder" },
{ id: 7, name: "Arda", role: "Midfielder" },
{ id: 8, name: "A. Iniesta", role: "Midfielder" },
{ id: 9, name: "Suárez", role: "Forward" },
{ id: 10, name: "Messi", role: "Forward" },
{ id: 11, name: "Neymar", role: "Forward" },
{ id: 12, name: "Rafinha", role: "Midfielder" },
{ id: 13, name: "Cillessen", role: "Goalkeeper" },
{ id: 14, name: "Mascherano", role: "Defender" },
{ id: 17, name: "Paco Alcácer", role: "Forward" },
{ id: 18, name: "Jordi Alba", role: "Defender" },
{ id: 19, name: "Digne", role: "Defender" },
{ id: 20, name: "Sergi Roberto", role: "Midfielder" },
{ id: 21, name: "André Gomes", role: "Midfielder" },
{ id: 22, name: "Aleix Vidal", role: "Midfielder" },
{ id: 23, name: "Umtiti", role: "Defender" },
{ id: 24, name: "Mathieu", role: "Defender" },
{ id: 25, name: "Masip", role: "Goalkeeper" }
);
getItems(): Array<Item> {
return this.items;
}
getItem(id: number): Item {
return this.items.filter((item) => item.id === id)[0];
}
}
export class Item {
constructor(public id: number, public name: string, public role: string) { }
}
Styling
The ListView supports the common CSS styling (e.g.,
padding, margin,
background-color, etc.). Additionally, you can use
separatorColor, rowHeight and
iosEstimatedRowHeight to further customize the
ListView's styles.
<!--
The @nativescript/theme provides ListView CSS classes (`list-group` & `list-group-item`) for setting recommended paddings & margins for ListView items.
These class names adds a bit of spacing and the theme’s color scheme.
-->
<ListView [items]="items" class="list-group"
backgroundColor="red" separatorColor="blue">
<ng-template let-item="item">
<GridLayout height="60">
<Label [text]="item.name" class="list-group-item" color="white"></Label>
</GridLayout>
</ng-template>
</ListView>
Tips And Tricks
Item Templates
Use itemTemplateSelector property to create
multiple item templates. The
itemTemplateSelector accepts a function that
returns a value for nsTemplateKey.
<ListView [items]="items" class="list-group" [itemTemplateSelector]="templateSelector" row="0">
<ng-template nsTemplateKey="red" let-item="item" let-i="index">
<GridLayout>
<Label [text]="item.name" backgroundColor="red" color="white"></Label>
</GridLayout>
</ng-template>
<ng-template nsTemplateKey="green" let-item="item" let-i="index">
<GridLayout>
<Label [text]="item.name" backgroundColor="green" color="yellow"></Label>
</GridLayout>
</ng-template>
</ListView>
import { Component, Input, OnChanges, SimpleChanges, OnInit } from "@angular/core";
import { ItemService, Item } from "../usage/usage.service";
import { ItemEventData } from "tns-core-modules/ui/list-view";
@Component({
moduleId: module.id,
templateUrl: "./tips-and-tricks.component.html"
})
export class ListViewTipsComponent implements OnInit {
items: Array<Item>;
constructor(private _itemService: ItemService) { }
ngOnInit(): void {
this.items = this._itemService.getItems();
}
onItemTap(args: ItemEventData) {
console.log(`Index: ${args.index}; View: ${args.view} ; Name: ${this.items[args.index].name}`);
}
templateSelector(item: Item, index: number, items: any) {
return index % 2 === 0 ? "red" : "green";
}
}
Custom Component Template
Common scenario in Angular is to reuse given component via its
selector name (e.g., sdk-child-component). The
below scenario demonstrates how to pass data from the parent
ListView to its children components (which are used
as template).
<ListView [items]="items" class="list-group" [itemTemplateSelector]="templateSelector" row="0">
<ng-template nsTemplateKey="red" let-item="item" let-i="index">
<GridLayout>
<Label [text]="item.name" backgroundColor="red" color="white"></Label>
</GridLayout>
</ng-template>
<ng-template nsTemplateKey="green" let-item="item" let-i="index">
<GridLayout>
<Label [text]="item.name" backgroundColor="green" color="yellow"></Label>
</GridLayout>
</ng-template>
</ListView>
import { Component, Input, OnChanges, SimpleChanges, OnInit } from "@angular/core";
import { ItemService, Item } from "../usage/usage.service";
import { ItemEventData } from "tns-core-modules/ui/list-view";
@Component({
moduleId: module.id,
templateUrl: "./tips-and-tricks.component.html"
})
export class ListViewTipsComponent implements OnInit {
items: Array<Item>;
constructor(private _itemService: ItemService) { }
ngOnInit(): void {
this.items = this._itemService.getItems();
}
onItemTap(args: ItemEventData) {
console.log(`Index: ${args.index}; View: ${args.view} ; Name: ${this.items[args.index].name}`);
}
templateSelector(item: Item, index: number, items: any) {
return index % 2 === 0 ? "red" : "green";
}
}
Properties
| Name | Type | Description |
|---|---|---|
items |
Array<any> | ItemsSource
|
Gets or set the items collection of the
ListView. The items property can be set to an
array or an object defining length and getItem(index)
method.
|
itemTemplateSelector |
function |
A function that returns the appropriate ket template based on the data item. |
itemTemplates |
Array<KeyedTemplate> |
Gets or set the list of item templates for the item template selector. |
separatorColor |
string | Color |
Gets or set the items separator line color of the ListView. |
rowHeight |
Length |
Gets or set row height of the ListView. |
iosEstimatedRowHeight |
Length |
Gets or set the estimated height of rows in the ListView. Default value: 44px |
Methods
| refresh() | Forces the ListView to reload all its
items. | | scrollToIndex(index: number) | Scrolls
the specified item with index into view. | |
scrollToIndexAnimated(index: number) | Scrolls the
specified item with index into view with animation. | |
isItemAtIndexVisible(index: number): boolean |
Checks if specified item with index is visible. |
Events
| Name | Description |
|---|---|
itemLoading |
Emitted when a View for the data at the
specified index should be created.
|
itemTap |
Emitted when a ListView item is tapped. |
loadMoreItems |
Emitted when the ListView is scrolled so that its last item is visible. |
API References
| Name | Type |
|---|---|
| tns-core-modules/ui/list-view | Module |
| ListView | Class |
| ItemEventData | Interface |
| ItemsSource | Interface |
| KeyedTemplate | Interface |
Native Component
| Android | iOS |
|---|---|
| android.widget.ListView | UITableView |