Have you seen all of the free code samples available on our Marketplace?

NativeScript Angular

Tab View

The TabView component provides a simple way to navigate between different views by tapping on some of the tabs or by swiping between the views. By default the TabView will load the view of the first tab, however it's possible to load alternative tabs when the app starts by setting the component’s selectedIndex property.

import { TabView } from "tns-core-modules/ui/tab-view";

The general behavior of the TabView component is to load its items on demand. This means that every TabViewItem view will be loaded when it is shown and will be unloaded when it disappears. Respectively, the loaded and unloaded events will be fired when navigating between views. However, there are some specifics for each platform (iOS and Android), which are described in the notes below.

Note (iOS specific): The iOS implementation uses UITabBarController. This means that only one TabViewItem can be shown at a given time and only one needs to be loaded. When the user selects a new TabViewItem, we load the new item and unload the previous one.

Note (Android specific): The Android implementation uses a ViewPager control, which allows using the swipe gesture to navigate to the next or previous tab. This means that only one TabViewItem can be shown, but multiple TabViewItems need to be loaded to the side. If this is not done, you will not be able to see the next TabViewItem contents during the swipe. By default, the ViewPager control will pre-load one TabViewItem on the left and on on the right. Regarding that, if one of the items is already pre-loaded, it will not be loaded again. In NativeScript, we have exposed a property called androidOffscreenTabLimit, which allows specifying how many components should be pre-loaded to the sides (if you are setting up androidOffscreenTabLimit to 0, the Android behavior will match to the iOS behavior).

The iOS and Android UX guidelines regarding the Tab controls differ greatly. The difference is described in the below points:

  • The iOS tabs have their tab bar, which will be displayed always on the bottom and does not allow swipe gesture for changing tabs.
  • The Android tabs are on top and will enable the swipe navigation between the tabs.
  • For Android we have androidTabsPosition property which has two options top(default value) and bottom. Setting up this property to bottom allows mimicking Bottom Tab Navigation control(provided by android support library v25 release). Setting the Tabs at the bottom will disable the swipe navigation and the items preloading functionality.

Image

Basics

Using a TabView inside an Angular app requires some special attention about how to provide title, iconSource and content (view) of the TabViewItem. In a pure NativeScript application TabView has an items property which could be set via XML to an array of TabViewItems (basically, an array of objects with title, view and iconSource properties). However, NativeScript-Angular does not support nested properties in its HTML template, so adding TabViewItem to TabView is a little bit different. NativeScript-Angular provides a custom Angular directive that simplifies the way native TabView should be used. The following example shows how to add a TabView to your page (with some clarifications later):

HTML

<TabView id="tabViewContainer">
    <StackLayout *tabItem="{title: 'First Tab', iconSource: 'res://icon'}">
        <StackLayout>
            <Label text="First Tab" textWrap="true" class="m-15 h2 text-left" color="blue"></Label>
        </StackLayout>
    </StackLayout>
    <StackLayout *tabItem="{title: 'Second Tab', iconSource: 'res://icon'}">
        <StackLayout>
            <Label text="Second Tab" textWrap="true" class="m-15 h2 text-left" color="blue"></Label>
        </StackLayout>
    </StackLayout>
</TabView>
  • tabItem: This directive uses a JSON object to transfer properties to the native object. Actually, TabViewItem is a pretty simple object with just title, iconSource and view properties. Since title and iconSource are usually represented as text, TabView directive uses a small JSON object ({title: 'Profile', iconSource: '~/icon.png'}) to define these properties easily in HTML. The view however, is not so simple, therefore the directive uses the tag where tabItem attribute is set as view. Currently, the directive also holds the property textTransform which controls the capitalization of the tab title text. See the Styling section for more information.

Note: If you have set the iconSource property on a TabViewItem, but are not seeing any icons next to the title, this might be because the icon is not present in your App_Resources folder. See the Working with Images article for information on how to add and reference your resource images.

Improve this document

Demo Source


To navigate between the different TabViewItem views programmatically, use the selectedIndex property. A typical way to do this in Angular would be set it up as two-way binding. Using this kind of binding is relatively simple. Just use the standard ngModel syntax and bind it to the data model property tabSelectedIndex. You can also handle user input navigations with the selectedIndexChanged event. The following example displays the scenario in practice.

HTML

<TabView [(ngModel)]="tabSelectedIndex" (selectedIndexChanged)="onSelectedIndexChanged($event)">
    <StackLayout *tabItem="{title: 'Profile'}">
        <StackLayout>
            <Label [text]="tabSelectedIndexResult" class="h2 m-t-16 text-center" textWrap="true"></Label>
            <Button text="Change Tab via ngModel" (tap)="changeTab()" class="btn btn-primary btn-active"></Button>
        </StackLayout>
    </StackLayout>
    <StackLayout *tabItem="{title: 'Stats'}">
        <StackLayout>
            <Label [text]="tabSelectedIndexResult" class="h2 m-t-16 text-center" textWrap="true"></Label>
            <Button text="Change Tab via ngModel" (tap)="changeTab()" class="btn btn-primary btn-active"></Button>
        </StackLayout>
    </StackLayout>
    <StackLayout *tabItem="{title: 'Settings'}">
        <StackLayout>
            <Label [text]="tabSelectedIndexResult" class="h2 m-t-16 text-center" textWrap="true"></Label>
            <Button text="Change Tab via ngModel" (tap)="changeTab()" class="btn btn-primary btn-active"></Button>
        </StackLayout>
    </StackLayout>
</TabView>

TypeScript

public tabSelectedIndex: number;
public tabSelectedIndexResult: string;

constructor() {
    this.tabSelectedIndex = 0;
    this.tabSelectedIndexResult = "Profile Tab (tabSelectedIndex = 0 )";
}

changeTab() {
    if (this.tabSelectedIndex === 0) {
        this.tabSelectedIndex = 1;
    } else if (this.tabSelectedIndex === 1) {
        this.tabSelectedIndex = 2;
    } else if (this.tabSelectedIndex === 2) {
        this.tabSelectedIndex = 0;
    }
}

// displaying the old and new TabView selectedIndex
onSelectedIndexChanged(args: SelectedIndexChangedEventData) {
    if (args.oldIndex !== -1) {
        const newIndex = args.newIndex;
        if (newIndex === 0) {
            this.tabSelectedIndexResult = "Profile Tab (tabSelectedIndex = 0 )";
        } else if (newIndex === 1) {
            this.tabSelectedIndexResult = "Stats Tab (tabSelectedIndex = 1 )";
        } else if (newIndex === 2) {
            this.tabSelectedIndexResult = "Settings Tab (tabSelectedIndex = 2 )";
        }
        alert(`Selected index has changed ( Old index: ${args.oldIndex} New index: ${args.newIndex} )`)
            .then(() => {
                console.log("Dialog closed!");
            });
    }
}

Improve this document

Demo Source


Offscreen Tab Limit Android

Use the androidOffscreenTabLimit property to set the number of pre-loaded side tabs on Android. The default value is 1.

HTML

<TabView id="tabViewContainer" androidOffscreenTabLimit="0">
    <StackLayout *tabItem="{title: 'First Tab', iconSource: 'res://icon'}">
        <Label text="First Tab" textWrap="true" class="m-15 h2 text-left" color="blue"></Label>
    </StackLayout>
    <StackLayout *tabItem="{title: 'Second Tab', iconSource: 'res://icon'}">
        <Label text="Second Tab" textWrap="true" class="m-15 h2 text-left" color="blue"></Label>
    </StackLayout>
</TabView>

Improve this document

Demo Source


Styling

The TabView component has the following unique styling properties:

  • selectedTabTextColor (corresponding CSS property selected-tab-text-color ) - change the color of the text, while selecting some of the tabs.

  • tabBackgroundColor (corresponding CSS property tab-background-color) - change the background of the tabs.

  • textTransform (corresponding CSS property text-transform) - set up textTransform individually for every TabViewItem. Value options: capitalize, lowercase, none, uppercase.

  • androidSelectedTabHighlightColorandroid specific property (corresponding CSS property android-selected-tab-highlight-color) - setup underline color of the Tabs in Android.

XML

<TabView id="tabViewContainer" selectedTabTextColor="purple" tabBackgroundColor="yellow" androidSelectedTabHighlightColor="red">
    <StackLayout *tabItem="{title: 'First Tab', iconSource: 'res://icon', textTransform: 'lowercase'}" >
        <Label text="First Tab" textWrap="true" class="m-15 h2 text-left" color="blue"></Label>
    </StackLayout>
    <StackLayout *tabItem="{title: 'Second Tab', iconSource: 'res://icon', textTransform: 'lowercase'}">
        <Label text="Second Tab" textWrap="true" class="m-15 h2 text-left" color="blue"></Label>
    </StackLayout>
</TabView>

Improve this document

Demo Source


Tabs Position Android

Use the androidTabsPosition property to change the position of the tabs on Android. The default value is top.

HTML

<TabView androidTabsPosition="bottom"  >
    <StackLayout *tabItem="{title: 'First Tab', iconSource: 'res://icon'}">
        <Label text="First Tab" textWrap="true" class="m-15 h2 text-left" color="blue"></Label>
    </StackLayout>
    <StackLayout *tabItem="{title: 'Second Tab', iconSource: 'res://icon'}">
        <Label text="Second Tab" textWrap="true" class="m-15 h2 text-left" color="blue"></Label>
    </StackLayout>
</TabView>

Improve this document

Demo Source


Title Icon Fonts

The example demonstrates, how to use Icon font for the TabView items title. For more information on how to add and use Icon fonts in your app, refer to the Icon Fonts article.

HTML

<TabView id="tabViewContainer" class="icon">
    <StackLayout *tabItem="{title: '&#xe913;'}">
        <Label text="First TabView item with Icon Font" textAlignment="center" textWrap="true" class="h2 m-x-auto" color="blue"></Label>
        <Label text="&#xe913;" textWrap="true" class="h2 m-x-auto" color="blue"></Label>
    </StackLayout>
    <StackLayout *tabItem="{title: '&#xe908;'}">
        <Label text="Second TabView item with Icon Font" textAlignment="center" textWrap="true" class="h2 m-x-auto" color="green"></Label>
        <Label text="&#xe908;" textWrap="true" class="h2 m-x-auto" color="green"></Label>
    </StackLayout>
</TabView>

CSS

.icon{
    font-family: 'icomoon';
}

Improve this document

Demo Source


API Reference for the TabView Class

Native Component

Android iOS
android.support.v4.view.ViewPager UITabBarController