Page-router-outlet to get the higher component - nativescript

I am working on nativescript angular project that using RadSideDrawer
And here my main-routing.module.ts
import { NgModule } from "#angular/core";
import { Routes } from "#angular/router";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { MainComponent } from "~/app/components/main/main.component";
const routes: Routes = [
{
path: "",
component: MainComponent,
children: [
{ path: "", redirectTo: "/home", pathMatch: "full" },
{ path: "home", loadChildren: "~/app/components/home/home.module#HomeModule" },
{
path: "browse",
loadChildren: "~/app/components/browse/browse.module#BrowseModule"
},
{
path: "search",
loadChildren: "~/app/components/search/search.module#SearchModule"
},
{
path: "featured",
loadChildren: "~/app/components/featured/featured.module#FeaturedModule"
},
{
path: "settings",
loadChildren: "~/app/components/settings/settings.module#SettingsModule"
}
]
}
];
#NgModule({
imports: [NativeScriptRouterModule.forChild(routes)],
exports: [NativeScriptRouterModule]
})
export class MainRoutingModule {}
here is my main.component.html
<RadSideDrawer [drawerTransition]="sideDrawerTransition">
<GridLayout tkDrawerContent rows="auto, *" class="sidedrawer sidedrawer-left">
<StackLayout row="0" class="sidedrawer-header">
<Label class="sidedrawer-header-image fa" text=""></Label>
<Label class="sidedrawer-header-brand" text="User Name"></Label>
<Label class="footnote" text="username#mail.com"></Label>
</StackLayout>
<ScrollView row="1">
<StackLayout class="sidedrawer-content">
<GridLayout columns="auto, *" class="sidedrawer-list-item" [class.selected]="isComponentSelected('/home')"
(tap)="onNavItemTap('/home')">
<Label col="0" text="" class="fa"></Label>
<Label col="1" text="Home" class="p-r-10"></Label>
</GridLayout>
<GridLayout columns="auto, *" class="sidedrawer-list-item" [class.selected]="isComponentSelected('/browse')"
(tap)="onNavItemTap('/browse')">
<Label col="0" text="" class="fa"></Label>
<Label col="1" text="Browse" class="p-r-10"></Label>
</GridLayout>
<GridLayout columns="auto, *" class="sidedrawer-list-item" [class.selected]="isComponentSelected('/search')"
(tap)="onNavItemTap('/search')">
<Label col="0" text="" class="fa"></Label>
<Label col="1" text="Search" class="p-r-10"></Label>
</GridLayout>
<GridLayout columns="auto, *" class="sidedrawer-list-item" [class.selected]="isComponentSelected('/featured')"
(tap)="onNavItemTap('/featured')">
<Label col="0" text="" class="fa"></Label>
<Label col="1" text="Featured" class="p-r-10"></Label>
</GridLayout>
<StackLayout class="hr-light"></StackLayout>
<GridLayout columns="auto, *" class="sidedrawer-list-item" [class.selected]="isComponentSelected('/settings')"
(tap)="onNavItemTap('/settings')">
<Label col="0" text="" class="fa"></Label>
<Label col="1" text="Settings" class="p-r-10"></Label>
</GridLayout>
<GridLayout columns="auto, *" class="sidedrawer-list-item" (tap)="signOut()">
<Label col="0" text="" class="fa"></Label>
<Label col="1" text="Signout" class="p-r-10"></Label>
</GridLayout>
</StackLayout>
</ScrollView>
</GridLayout>
<page-router-outlet tkMainContent class="page page-content"></page-router-outlet>
</RadSideDrawer>
here is my app-routing.module.ts
import { NgModule } from "#angular/core";
import { Routes } from "#angular/router";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { AuthGuard } from "~/app/shared/services/auth-guard.service";
import { LogGuard } from "~/app/shared/services/log-guard.service";
const routes: Routes = [
{
path: "",
loadChildren: "~/app/components/main/main.module#MainModule",
canActivate: [AuthGuard]
},
{
path: "login",
loadChildren: "~/app/components/login/login.module#LoginModule",
canActivate: [LogGuard]
},
{
path: "register",
loadChildren: "~/app/components/register/register.module#RegisterModule",
canActivate: [LogGuard]
}
];
#NgModule({
imports: [NativeScriptRouterModule.forRoot(routes)],
exports: [NativeScriptRouterModule]
})
export class AppRoutingModule {}
and here my app.component.html
<app-no-connection></app-no-connection>
<page-router-outlet></page-router-outlet>
and here my home.component.html
<ActionBar class="action-bar">
<NavigationButton ios:visibility="collapsed" icon="res://menu" (tap)="onDrawerButtonTap()"></NavigationButton>
<ActionItem icon="res://navigation/menu" android:visibility="collapsed" (tap)="onDrawerButtonTap()" ios.position="left">
</ActionItem>
<Label class="action-bar-title" text="Home"></Label>
</ActionBar>
<GridLayout class="page page-content">
<Label class="page-icon fa" text=""></Label>
<Label class="page-placeholder" text="<!-- Page content goes here -->"></Label>
</GridLayout>
and here my home.component.ts
import { Component, OnInit } from "#angular/core";
import { RadSideDrawer } from "nativescript-ui-sidedrawer";
import * as app from "tns-core-modules/application";
#Component({
selector: "Home",
moduleId: module.id,
templateUrl: "./home.component.html"
})
export class HomeComponent implements OnInit {
constructor() {
// Use the component constructor to inject providers.
console.log("ini home");
}
ngOnInit(): void {
// Init your component properties here.
}
onDrawerButtonTap(): void {
console.log("tapped side bar");
const sideDrawer = <RadSideDrawer>app.getRootView();
sideDrawer.showDrawer();
}
}
my RadSideDrawer is not in app.component.html. It is in main.component.html. so in my app.component.html just has <page-router-outlet></page-router-outlet>.
I did like that because I need to login first before get the MainComponent.
But. It doesn't work. my RadSideDrawer not shown. And I don't understand why i got this error ERROR TypeError: sideDrawer.showDrawer is not a function when i tap drawer on home.component.html
Any suggestion please?

<RadSideDrawer [drawerTransition]="sideDrawerTransition" tkExampleTitle tkToggleNavButton>
<StackLayout tkDrawerContent class="sideStackLayout">
<!-- Your navigation drawer items -->
</StackLayout>
<page-router-outlet tkMainContent></page-router-outlet>
</RadSideDrawer>
AppComponent
#ViewChild(RadSideDrawerComponent) public drawerComponent: RadSideDrawerComponent;
private drawer: RadSideDrawer;
ngAfterViewInit() {
this.drawer = this.drawerComponent.sideDrawer;
this.drawer.gesturesEnabled = false; // To disbale the drawer.
}
// Code to enable Drawer:
this.drawer.gesturesEnabled = true;
// Controll sidedrawer from Other Screen
sideDrawer = <RadSideDrawer>app.getRootView();
this.sideDrawer.gesturesEnabled = true;

Related

RadAutoCompleteTextView showing "no result found error" in first build

While using RadAutoCompleteTextView in nativescript-angular app,I'm facing this weird problem:
I build my project using "tns build android --bundle".App starts but RadAutocompleteCompleteTextView shows
"no result found" although data bound to items attribute logs on terminal.
Now,if I make a minor change in my code(like delete a comment),it detect changes and auto rebuild again and this time AutocompleteView shows the data it was binding to.
Also,now if I run my app over usb debugging it runs well but if I remove usb and restart app it shows error
Error:View already has a parent
Here are the html and ts files :
app.component.html
<ActionBar title="Lestrange" class="actionbar" [height]="abarVisible">
<!-- <Image src="~/app/assets/men.png" height='50' width='50'></Image>-->
<NavigationButton icon="~/app/assets/menu.png" (tap)="onOpenDrawerTap()" [visibility]="getMenuVisible ? 'visible' : 'hidden'"></NavigationButton>
<ActionItem class="name" [visibility]="SearchVisible ? 'visible' : 'hidden'">
<StackLayout backgroundColor="#66cdaa" height="60" width="150" #action>
<RadAutoCompleteTextView [items]="searchdata" (didAutoComplete)="onDidAutoComplete($event)" *ngIf="searchdata" #aitem>
<SuggestionView tkAutoCompleteSuggestionView>
<ng-template tkSuggestionItemTemplate let-item="item">
<StackLayout orientation="vertical" padding="10">
<ImageCacheIt [src]="item.image" class='img' height='170' width='100' stretch="fill"></ImageCacheIt>
<Label [text]="item.id"></Label>
</StackLayout>
</ng-template>
</SuggestionView>
</RadAutoCompleteTextView>
</StackLayout>
</ActionItem>
<ActionItem>
<Label text="Search" color="white" (tap)="opensearch()"></Label>
</ActionItem>
</ActionBar>
<RadSideDrawer backgroundColor="transparent" id="rd" [gesturesEnabled]="sideDrawerEnabled">
<GridLayout tkDrawerContent rows="auto, *, auto" class="root-drawer-content">
<StackLayout tkDrawerContent>
<StackLayout height="56" marginTop="50" style="text-align: center; vertical-align: center;">
<Label text="Menu" fontSize="27"></Label>
</StackLayout>
<StackLayout margin="25">
<Label text="Home" [nsRouterLink]="['/hh']" padding="10" (tap)="onCloseDrawerTap()" fontSize="20" class="lbl"></Label>
<Label text="Live" [nsRouterLink]="['/lil']" padding="10" (tap)="onCloseDrawerTap()" fontSize="20" class="lbl"> </Label>
<Label text="Movies" [nsRouterLink]="['/moe']" padding="10" (tap)="onCloseDrawerTap()" fontSize="20" class="lbl"></Label>
<Label text="TV Shows" [nsRouterLink]="['/ss']" padding="10" (tap)="onCloseDrawerTap()" fontSize="20" class="lbl"></Label>
<Label text="Hindi" [nsRouterLink]="['/dhh']" padding="10" (tap)="onCloseDrawerTap()" fontSize="20" class="lbl"></Label>
</StackLayout>
<Label text="Logout" color="lightgray" padding="15" style="horizontal-align: center" (tap)="logout()" fontSize="20"> </Label>
</StackLayout>
</GridLayout>
<page-router-outlet tkMainContent actionBarVisibility="never"></page-router-outlet>
</RadSideDrawer>
app.component.ts:`
import {registerElement} from "nativescript-angular/element-registry";
registerElement("exoplayer", () => require("nativescript-exoplayer").Video);
import { Component,OnInit, ViewChild,AfterViewInit,OnChanges,AfterContentInit} from "#angular/core";
//import { isAndroid } from "tns-core-modules/platform";
import { Page } from "tns-core-modules/ui/page";
import { RouterExtensions } from "nativescript-angular/router";
import * as ApplicationSettings from "#nativescript/core/application-settings";
const firebase = require("nativescript-plugin-firebase");
import { RadSideDrawerComponent} from "nativescript-ui-sidedrawer/angular";
import {FirebaseService} from '../app/services/firebase.service';
import { RadAutoCompleteTextViewComponent } from "nativescript-ui-autocomplete/angular";
import { TokenModel, AutoCompleteCompletionMode, AutoCompleteDisplayMode, AutoCompleteSuggestMode } from "nativescript-ui-autocomplete";
import { ObservableArray } from "tns-core-modules/data/observable-array"
import { Observable } from "rxjs";
import "rxjs/add/operator/merge";
import { MovieModel } from "./models/movie.model";
import { NavigationExtras } from "#angular/router";
​
#Component({
selector: "ns-app",
templateUrl: "app.component.html"
})
export class AppComponent implements OnInit,AfterViewInit,AfterContentInit{
​
#ViewChild(RadSideDrawerComponent, { static: false }) public drawerComponent: RadSideDrawerComponent;
​
public isAuth: boolean;
public sideDrawerEnabled:boolean=false;
public getMenuVisible:boolean=true;
public abarVisible:number=70;
public searchvar: boolean;
public searchdata: ObservableArray<MovieModel>;
public searchdata1: ObservableArray<MovieModel>;
​
public datas$:Observable<any>;
public SearchVisible: boolean=false;
​
constructor(private page: Page,public router:RouterExtensions,public firebaseService: FirebaseService) { }
ngAfterContentInit(): void {
}
ngAfterViewInit(): void {
// //ApplicationSettings.setBoolean("authenticated", false);
// console.log(this.searchdata);
// //},2);
}
​
​
​
public ngOnInit() {
firebase.init({
}).then(
() => {
console.log("firebase.init done");
},
error => {
console.log(`firebase.init error: ${error}`);
}
);
/////////////////////////////////////////////////////
// console.log("fir"+this.getMenuVisible);
this.firebaseService.AbarVisibleEnabled.subscribe(x=>this.abarVisible=x);
this.firebaseService.SearchVisibleEnabled.subscribe(x=>this.SearchVisible=x);
​
this.firebaseService.sideDrawerEnabled.subscribe(x=>this.sideDrawerEnabled=x);
this.firebaseService.MenuVisibleEnabled.subscribe(y=>this.getMenuVisible=y);
// console.log("fir"+this.getMenuVisible);
this.searchdata = new ObservableArray<MovieModel>();
this.datas$ = <any>this.firebaseService.getMyWishList('/index');
// this.searchdata=this.firebaseService.fetchsearchdata();
// this.searchdata1=this.searchdata;
// console.log(this.searchdata);
// // setTimeout(()=>{
this.datas$.subscribe(datas=>{
datas.map(x=>{console.log(x);
this.searchdata.push(new MovieModel(x.id,x.c,x.img));
})
});
//this.drawer = this.drawerComponent.sideDrawer;
if(this.router.router.url==='/login'){
this.isAuth=true;
}else{
this.isAuth=false;
}
}
​
public onDidAutoComplete(args) {
this.SearchVisible=false;
console.log(args.text.split(",")[0]);
console.log(args.text.split(",")[1].trim());
this.searchvar=false;
​
let navigationExtras: NavigationExtras = {
queryParams: {
"showId": args.text.split(",")[0].trim(),
"fromRoute":args.text.split(",")[1].trim()
​
}
};
this.router.navigate(["/show-detail"],navigationExtras);
}
onOpenDrawerTap() {
this.drawerComponent.sideDrawer.showDrawer();
}
onCloseDrawerTap() {
this.drawerComponent.sideDrawer.closeDrawer();
}
​
get dataItems(): ObservableArray<MovieModel> {
return this.searchdata;
}
opensearch(){
this.SearchVisible=!this.SearchVisible;
}
​
public logout() {
this.onCloseDrawerTap();
ApplicationSettings.setBoolean("authenticated", false);
//ApplicationSettings.remove("authenticated");
this.router.navigate(["/login"], { clearHistory: true });
}
}
`
Although I don't have much knowledge about angular lifecycle hooks but I have a feeling that its about angular hooks ,So I tried to use differnet hooks but to no avail.Please help me find the issue in my code.Thanks in advance.
It looks like you have an unpaired </StackLayout> tag in your html file. It is right after `.
I think you should remove that and see if that resolves the issue.
Hope this helps!

How to Expand only one item in collapsible list with NativeScript

I have built a RadListview with nativescript. But now I want that if I tap on an item then only that item should open and other Expanded items should close.
I followed this Creating a collapsible list with NativeScript and it works, I just need one item expanding at a time
enter image description here
thank you
export class RoadComponent {
public roads: Array<any>;
constructor(private page:Page,private router: Router, private roadService: RoadService,private back:BackendService) {
}
async ngOnInit() {
this.roads = await this.roadService.getRoads();
}
templateSelector(item: any, index: number, items: any): string {
return item.expanded ? "expanded" : "default";
}
onItemTap(event: ListViewEventData) {
var listView = event.object as RadListView,
rowIndex = event.index,
dataItem = event.view.bindingContext;
dataItem.expanded = !dataItem.expanded; listView.androidListView.getAdapter().notifyItemChanged(rowIndex);
}
}
<Page>
<StackLayout>
<RadListView multipleSelection="false" id="abc" height="100%" [items]="roads" [itemTemplateSelector]="templateSelector" class="list-group" (itemTap)="onItemTap($event)">
<ng-template tkListItemTemplate let-item="item">
<StackLayout id="abc" orientation="vertical">
<Label text="{{item.name}}" class="list-group-item">
</Label>
</StackLayout>
</ng-template>
<ng-template tkTemplateKey="expanded" let-item="item">
<GridLayout rows="auto,auto" columns="*,*" class="list-group-item add-dropdown">
<Label row="0" col="0" text="{{item.name}}" class="list-group-item"></Label>
<Button row="1" col="0" text="{{item.id}}" (tap)="navigatetomap(item.name)" [nsRouterLink]="['/accueil', { outlets: { homeoutlet: ['home'] } }]"></Button>
<Button row="1" col="1" text="{{item.name}}"></Button>
</GridLayout>
</ng-template>
</RadListView>
</StackLayout>
</Page>
if anyone had this issue just make expanded property false to all the items
onItemTap(event: ListViewEventData) {
for(let i=0;i<this.roads.length;i++){
this.roads[i].expanded=false;
}
var listView = event.object as RadListView,
rowIndex = event.index,
dataItem = event.view.bindingContext;
dataItem.expanded = !dataItem.expanded;
listView.androidListView.getAdapter().notifyItemChanged(rowIndex);
}

The spacing issue comes when using the side drawer and scroll view in native script angular

I am developing android and ios applications using native script-angular. I am using UISidedrawer plugin for showing the menu's, I have an issue while using UISidedrawer and ScrollView same time, In my component, space was automatically taken. Here are my code and screenshot.
I am creating a side drawer and menu's like:
<RadSideDrawer [transition]="drawerTransition">
<GridLayout rows="auto,*,110" column="auto" tkDrawerContent height="100%">
<StackLayout row="0" column="0" orientation="vertical" class="sidedrawer-header">
<Label class="italic" text="Welcome "></Label>
</StackLayout>
<ListView row="1" column="0" [items] = "navMenu" rowHeight="40" class="sidedrawer-content" separatorColor="#40053e" (itemLoading)="onItemLoading($event)">
<ng-template>
<StackLayout
//code
</StackLayout>
</ng-template>
</ListView>
<StackLayout row="2" column="0" class="sidedrawer-footer" orientation="vertical">
<Button text="Logout" (tap)="logout()" pageTransition="slideright"></Button>
</StackLayout>
</GridLayout>
<StackLayout tkMainContent>
<StackLayout>
<ng-content></ng-content>
</StackLayout>
</StackLayout>
</RadSideDrawer>
My side drawer component.ts code
import { RadSideDrawerComponent, SideDrawerType } from 'nativescript-ui-sidedrawer/angular';
import { SlideInOnTopTransition } from 'nativescript-ui-sidedrawer';
#Component({
moduleId: module.id,
selector: "side-drawer",
templateUrl: 'side-drawer.component.html',
styleUrls: ['side-drawer.component.css']
})
export class SideDrawerComponent implements AfterViewInit, OnDestroy, OnInit {
#ViewChild(RadSideDrawerComponent) drawerComponent: RadSideDrawerComponent;
private drawer: SideDrawerType;
drawerTransition: any;
navMenu: any[] = [
{id: '0', name: 'Dashboard', icon: '~/Images/dashboard.png', commands: ['/dashboard'] },
{id: '1', name: 'Status', icon: '~/Images/progress.png', commands: ['/status'] },
{id: '2', name: 'Transcript', icon: '~/Images/send.png', commands: ['/transcript'] },
{id: '3', name: 'Change Password', icon: '~/Images/password.png', commands: ['/password'] },
{id: '4', name: 'Support', icon: '~/Images/contact.png', commands: ['/contact'] },
{id: '5', name: 'About Us', icon: '~/Images/about.png', commands: ['/about'] },
{id: '6', name: 'FAQ', icon:'~/Images/faq.png',commands:['/faq']},
];
constructor( ) {
this.drawerTransition = new SlideInOnTopTransition();
}
ngAfterViewInit() {
this.drawer = this.drawerComponent.sideDrawer;
}
}
My menu content html
<side-drawer>
<GridLayout rows="*,100">
<StackLayout row="0" orientation="vertical">
<StackLayout orienatation="vertical">
<ScrollView>
<Label text="Hello World> </Label>
</ScrollView>
</StackLayout>
</StackLayout>
<StackLayout row="1">
</StackLayout>
</GridLayout>
</side-drawer>
How to remove unwanted space. Only the space issue occurs when we use a scroll view inside the side drawer and ios platform only.

Why is this route not routing through `page-router-outlet`?

I'm trying to have a component that has an ActionBar and child components that are accessed by page-router-outlet.
My HTML for the parent component is as follows:
<ActionBar class="action-bar">
<NavigationButton ios:visibility="collapsed" icon="res://menu" (tap)="onDrawerButtonTap()"></NavigationButton>
<ActionItem icon="res://navigation/menu" android:visibility="collapsed" (tap)="onDrawerButtonTap()"
ios.position="left">
</ActionItem>
<Label class="action-bar-title" text="Example Text"></Label>
</ActionBar>
<RadSideDrawer #drawer showOverNavigation="true" [drawerTransition]="sideDrawerTransition">
<StackLayout tkDrawerContent>
<MyDrawer [selectedPage]="'Settings'"></MyDrawer>
</StackLayout>
<StackLayout class="page page-content" tkMainContent>
<page-router-outlet></page-router-outlet>
</StackLayout>
</RadSideDrawer>
My routing-module for the parent component looks like:
import {NgModule} from '#angular/core';
import {Routes} from '#angular/router';
import {NativeScriptRouterModule} from 'nativescript-angular/router';
import {HomeComponent} from './home.component';
import {DashboardComponent} from '../dashboard/dashboard.component';
import {Dashboard2Component} from '../dashboard2/dashboard.component';
const routes: Routes = [
{
path: '',
component: HomeComponent,
children: [
{path: '', component: DashboardComponent},
{path: 'projects', component: Dashboard2Component},
]
}
];
#NgModule({
imports: [NativeScriptRouterModule.forChild(routes)],
exports: [NativeScriptRouterModule]
})
export class HomeRoutingModule {
}
export const routedComponents = [
HomeComponent
];
However, when I route to /projects, it brings me to a new page with a new actionbar
It's my understanding that this is because page-router-outlet creates a new page, that being said, I want to be able to navigate back from one child component back to the previous child component. Is this possible in {N}?
Make the main template for your app as a component...
app-template.component.html:
<ActionBar class="action-bar">
<NavigationButton class="action-item" icon="res://ic_menu" (tap)="toggleDrawer()"></NavigationButton>
<StackLayout class="action-bar-title">
<Label [text]="title"></Label>
</StackLayout>
</ActionBar>
<RadSideDrawer showOverNavigation="true">
<ScrollView tkDrawerContent class="sidedrawer-center" tkDrawerClosed="onDrawerClosed" tkDrawerClosing="onDrawerClosing" tkDrawerOpened="onDrawerOpened" tkDrawerOpening="onDrawerOpening">
<StackLayout>
<StackLayout class="sidedrawer-header">
<Label text="blah blah blah" class="text-left text-capitalize font-weight-bold text-primary" textWrap="true"></Label>
</StackLayout>
<StackLayout class="sidedrawer-content">
<GridLayout (tap)="closeDrawer()" nsRouterLinkActive="active" [nsRouterLinkActiveOptions]="{exact: true}" [nsRouterLink]="['/']" class="sidedrawer-list-item" pageTransition="fade" rows="auto" columns="auto, *">
<Label class="sidedrawer-list-item-text" row="0" col="1" text="Home"></Label>
</GridLayout>
<GridLayout (tap)="closeDrawer()" nsRouterLinkActive="active" [nsRouterLink]="['/settings']" class="sidedrawer-list-item" pageTransition="fade" rows="auto" columns="auto, *">
<Label class="sidedrawer-list-item-text" row="0" col="1" text="Settings"></Label>
</GridLayout>
</StackLayout>
</StackLayout>
</ScrollView>
<StackLayout tkMainContent class="page">
<ng-content></ng-content>
</StackLayout>
</RadSideDrawer>
app-template.component.ts:
import { Component, ViewChild, Input, OnInit } from "#angular/core";
import { RadSideDrawer, PushTransition } from "nativescript-telerik-ui/sidedrawer";
import { RadSideDrawerComponent } from "nativescript-telerik-ui/sidedrawer/angular";
#Component({
selector: "app-template",
moduleId: module.id,
templateUrl: './app-template.component.html'
})
export class AppTemplateComponent {
canToggleDrawer: boolean = true;
constructor() { }
#Input() title: string = 'MyApp';
#ViewChild(RadSideDrawerComponent) drawerComponent: RadSideDrawerComponent;
drawer: RadSideDrawer;
ngOnInit() {}
ngAfterViewInit() {
this.drawer = this.drawerComponent.sideDrawer;
this.drawer.drawerTransition = new PushTransition();
}
toggleDrawer() {
if (this.canToggleDrawer) {
this.drawer.toggleDrawerState();
}
}
closeDrawer() {
this.drawer.closeDrawer();
}
}
then on your child views, just call it as <app-template> and put your content inside it. This way, you can keep your drawer menu in one file only, and still be able to use the back buttons...

Filter ListView using angular2 in NativeScript

I am new to nativescript and angular2. I want to filter listview using textfield input entered by user. in angular version 1, we used to do it like
<input type="text" ng-model="userinput">
<div ng-repeat="x in items | filter : userinput">
</div>
how can i do this using angular2 in nativescript?
my listview is:
<ListView [items]="myItems" class="list-group">
<template let-item="item">
<StackLayout>
<Label [text]='item.Department' class="list-group-item"></Label>
</StackLayout>
</template>
</ListView>
and in my component:
export class someComponent {
public myItem: Array<any>;
public isLoading: boolean;
public constructor(private http: Http) {
this.myItem = [];
this.isLoading = true;
}
public ngOnInit()
{
this.http.get("some_api_url")
.map(result => result.json())
.do(result => console.log(JSON.stringify(result)))
.subscribe(result => {
this.myItem = result;
this.isLoading = false;
}, error => {
console.log("ERROR: ", error);
});
}
}
You had to create a pipe for filtering first, something like:
#Pipe({
name: 'filter'
})
#Injectable()
export class FilterPipe implements PipeTransform {
transform(items: any[], field : string, value : string): any[] {
if (!items) return [];
return items.filter(it => it[field] == value);
}
}
Usage:
<li *ngFor="let it of its | filter : 'name' : 'value or variable'">{{it}}</li>
The nativescript ui listview filtering is slow when the data is huge and it does "remove" the no match item. I change a bit code to make it fast and only show filtered data. :)
happy coding :)
Page class="page">
<StackLayout orientation="vertical">
<GridLayout rows="auto,auto,*,auto">
<StackLayout class="form" row="0" orientation="horizontal" width="100%">
<TextField hint="Search..." class="input"
id= "searchstr"
[(ngModel)]="searchstr"
width="80%"></TextField>
<Button class="btn-sm btn-primary btn-active"
id="btnSearch"
(tap)="onSearchTap($event)"
width="20%" height="40" >
<FormattedString>
<Span [text]="iconval" class="icon"></Span>
</FormattedString>
</Button>
</StackLayout>
<StackLayout row="1" orientation="horizontal" width="100%" backgroundcolor="black">
<Label text="CODE" width="25%" class="caption"></Label>
<Label text="NAME" width="75%" class="caption"></Label>
</StackLayout>
<ScrollView row="2" tkExampleTitle tkToggleNavButton>
<RadListView [items]="dataItems"
(itemLoading)="onItemLoading($event)">
<ListViewLinearLayout
tkListViewLayout scrollDirection="Vertical"
itemInsertAnimation="Slide"
itemDeleteAnimation="Slide"></ListViewLinearLayout>
<ng-template tkListItemTemplate let-item="item" let-i="index" let-odd="odd" let-even="even">
<StackLayout class="list-item"
(tap)="onItemTap(item)"
orientation="horizontal" width="100%">
<Label [text]="item.custCode" width="25%"></Label>
<Label [text]="item.custName" width="75%"></Label>
</StackLayout>
</ng-template>
</RadListView>
</ScrollView>
</GridLayout>
</StackLayout>
</Page>
import { Component, OnInit } from '#angular/core';
import { ListViewEventData } from 'nativescript-ui-listview';
import { Color } from 'tns-core-modules/color/color';
import { APIService } from '~/app/core/services';
import { Observable } from 'rxjs';
import { CustProfileLight } from '~/app/core/model';
import { ObservableArray } from 'tns-core-modules/data/observable-array/observable-array';
#Component({
selector: 'ns-customer-lookup',
templateUrl: './customer-lookup.component.html',
styleUrls: ['./customer-lookup.component.css'],
moduleId: module.id,
})
export class CustomerLookupComponent implements OnInit {
private _dataItems: ObservableArray<CustProfileLight>;
customer$:Observable<CustProfileLight>
iconval:string;
search:string;
searchstr:string;
items:any;
//private _myFilteringFunc: (item: any) => any;
constructor(private serv:APIService) { }
ngOnInit() {
this.iconval = String.fromCharCode(0xe986);
this.serv.getCustomer().subscribe(resp=>{
this.items = resp;
this._dataItems = new ObservableArray<CustProfileLight>(resp);
})
}
get dataItems(): ObservableArray<CustProfileLight> {
return this._dataItems;
}
onItemLoading(args: ListViewEventData){
if (args.index % 2 === 0) {
args.view.backgroundColor = new Color("#b3ecff");
}
}
onItemTap(item){
}
onSearchTap(e){
const key =this.searchstr;
console.log(key);
let data= this.items.filter(item=>item.custCode.includes(key) ||
item.custName.includes(key) ||
item.address1.includes(key) ||
item.address2.includes(key) ||
item.address3.includes(key) ||
item.address4.includes(key) ||
item.city.includes(key) ||
item.state.includes(key) ||
item.postalCode.includes(key) ||
item.tel.includes(key) ||
item.fax.includes(key) ||
item.contactPerson.includes(key)
);
this._dataItems = new ObservableArray<CustProfileLight>(data);
}
// get FilteringFunc(): (item: any) => any {
// return this._myFilteringFunc;
// }
// set FilteringFunc(value: (item: any) => any) {
// this._myFilteringFunc = value;
// }
}

Resources