Search code examples
listviewnavigation-drawernativescriptangular2-nativescriptnativescript-telerik-ui

Can a ListView be used within a SideDrawer in NativeScript?


I need to implement a SideDrawer in NativeScript with the menu entries that can change dynamically depending on some conditions.

I decided to use the ListView to display the menu entries because the list could be long and scroll will be likely needed.

However, I can't seem to get it working and I can't find the reason why. The documentation for NativeScript for Angular is a bit incomplete and I'm not sure if I'm assembling the pieces correctly.

The SideDrawer is working correctly however the ListView is not shown. Note that if I add the elements using a StackLayout instead of a ListView they are displayed.

This is the template I'm working on:

<ActionBar title="Inline" >
    <NavigationButton [visibility]="hideDrawer || (isAndroid ? 'visible' : 'collapse')" icon="res://ic_menu" (tap)="onDrawerTap()"></NavigationButton>
    <ActionItem [visibility]="hideDrawer || (isAndroid ? 'collapse' : 'visible')" icon="res://ic_menu" ios.position="right" (tap)="onDrawerTap()"></ActionItem>
</ActionBar>

<RadSideDrawer #drawer>

    <StackLayout tkDrawerContent class="sideStackLayout">

        <GridLayout>
            <RadListView [items]="menuEntries" orientation="vertical">
                <template tkListItemTemplate let-item="item">
                    <StackLayout>
                        <Label [text]="item.label"  class="sideLabel"></Label>
                    </StackLayout>
                </template>
            </RadListView>
        </GridLayout>

    </StackLayout>

    <StackLayout tkMainContent>



    </StackLayout>

</RadSideDrawer>

and this is the code of the component, I removed the non relevant logic:

import * as application from "application";
import { Component, ViewChild, OnInit } from "@angular/core";
import { RadSideDrawerComponent, SideDrawerType } from "nativescript-telerik-ui/sidedrawer/angular";
import * as applicationSettings from "application-settings";

class MenuEntry {
    constructor(
        public label: string,
        public url: string
    ){}
}

@Component({
    selector: "main-container",
    templateUrl: 'app.component.html',
    styleUrls: ['app.component.css']

})
export class AppComponent implements OnInit {

    @ViewChild(RadSideDrawerComponent)
    public drawerComponent: RadSideDrawerComponent;
    private drawer: SideDrawerType;
    isAndroid:boolean = application.android !== null;
    hideDrawer = false;
    menuEntries:Array<MenuEntry> = [];

    constructor() {}

    ngAfterViewInit() {
        this.drawer = this.drawerComponent.sideDrawer;
    }

    public onDrawerTap() {
        this.drawer.toggleDrawerState();
    }

    public closeDrawer(){
        this.drawer.closeDrawer();
    }

    ngOnInit(){
        this.generateMenu();
    }

    private generateMenu(): void {
        this.menuEntries.push(
            new MenuEntry("LABEL1", "/place1"),
            new MenuEntry("LABEL2", "/place2")
        );
    }


}

I'm using:

  • nativescript: 2.2.1
  • nativescript-angular: 0.3.1
  • nativescript-telerik-ui: 1.3.1

Any suggestions?

Thanks


Solution

  • To be able to use the Both SideDrawer and RadListview components you should first add NativeScriptUISideDrawerModule and NativeScriptUIListViewModule in the imports in app.module.ts file. For further info how to use ListView inside the SideDrawer review the below-attached example.

    app.module.ts

    import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
    import { NativeScriptModule } from "nativescript-angular/nativescript.module";
    import { AppRoutingModule } from "./app.routing";
    import { AppComponent } from "./app.component";
    
    import { ItemService } from "./item/item.service";
    import { ItemsComponent } from "./item/items.component";
    import { ItemDetailComponent } from "./item/item-detail.component";
    import { NativeScriptUIListViewModule } from "nativescript-telerik-ui-pro/listview/angular";
    import { NativeScriptUISideDrawerModule } from "nativescript-telerik-ui-pro/sidedrawer/angular";
    @NgModule({
        bootstrap: [
            AppComponent
        ],
        imports: [
            NativeScriptModule,
            AppRoutingModule,
            NativeScriptUIListViewModule,
            NativeScriptUISideDrawerModule
        ],
        declarations: [
            AppComponent,
            ItemsComponent,
            ItemDetailComponent
        ],
        providers: [
            ItemService
        ],
        schemas: [
            NO_ERRORS_SCHEMA
        ]
    })
    export class AppModule { }
    

    items.component.html

    <GridLayout rows="" columns="">
    <RadSideDrawer #drawer>
        <StackLayout tkDrawerContent class="sideStackLayout" backgroundColor="red">
            <StackLayout class="sideTitleStackLayout" >
                <Label text="Navigation Menu"></Label>
            </StackLayout>
            <GridLayout class="sideStackLayout">
                <RadListView [items]="myItems" heigh="400">
                    <ng-template tkListItemTemplate let-item="item" let-i="index" let-odd="odd" let-even="even">
                        <StackLayout  orientation="vertical">
                            <Label [text]='"index: " + i'></Label>
                            <Label [text]='"[" + item.id +"] " + item.name'></Label>
                        </StackLayout>
                    </ng-template>
                </RadListView>
            </GridLayout>
        </StackLayout>
        <StackLayout tkMainContent>
            <Label text="Main page" textWrap="true" class="drawerContentText"></Label>
        </StackLayout>
    </RadSideDrawer>
    </GridLayout>
    

    items.component.ts

    import { Component, ElementRef, ViewChild, Injectable, AfterViewInit, OnInit, ChangeDetectorRef } from "@angular/core";
    
    
    class DataItem{
        constructor(public id:number, public name:string){}
    }
    
    import { Item } from "./item";
    import { ItemService } from "./item.service";
    
    @Component({
        selector: "ns-items",
        moduleId: module.id,
        templateUrl: "./items.component.html",
    })
    export class ItemsComponent{
        public myItems: Array<DataItem>;
        private counter: number;
    
        constructor() {
            this.myItems = [];
            this.counter = 0;
            for (var i = 0; i < 50; i++) {
                this.myItems.push(new DataItem(i, "data item " + i));
                this.counter = i;
            }
        }
    }