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

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...

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!

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.

Page-router-outlet to get the higher component

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;

Nativescript: Display image from url array from a collection/array using ListView

this is the JSON data that I got from a REST API:
[{
"name": "sherwin",
"field2": "value2",
"field3": "value3",
"images": [{
"image": "url1", "image":"url2"....}]
"fieldN":"valueN"
}]
... and I have the following ListItem on a page:
<ListView [items]="propertyList" class="image-list" (loaded)="onListViewLoaded($event)">
<ng-template let-item="item">
<StackLayout style="height: 200" (tap)="onItemTap(item.id)"
id="{{item.id}}" (loaded)="onItemLoaded($event, item.images)">
<StackLayout class="image-container">
<Image [src]="item.images[0].image" stretch="aspectFill" class="image-content-container"></Image>
</StackLayout>
<StackLayout class="image-caption-container">
<Label id="{{item.id}}"
[text]="item.propertyName"
class="image-caption"></Label>
<Label class="gh-list-description-sub" text="{{item.propertyType}}" textWrap="true"></Label>
</StackLayout>
</StackLayout>
</ng-template>
</ListView>
... but the problem is the image not displaying once the list item were populated. The 'labels' was displaying though. I tried data/observable on the code-behind:
export class MainComponent extends Observable implements OnInit, AfterViewInit {
private propertyList = new ObservableArray();
... some other codes here
but I am not going anywhere.
Need help.
I've seen some strange behaviour using Image on ListView in the latest NativeScript version 3.1
Images are not displayed until you scroll down and up!!
As a workaround you can use WebImage component from nativescript-web-image-cache plugin.
First install it:
tns plugin add nativescript-web-image-cache
initialize the plugin on your root component AppComponent, app.component.ts:
import { Component } from "#angular/core";
import { OnInit } from '#angular/core/core';
import { initializeOnAngular } from 'nativescript-web-image-cache';
#Component({
selector: "ns-app",
templateUrl: "app.component.html",
})
export class AppComponent implements OnInit {
ngOnInit():void {
initializeOnAngular();
}
}
In your template replace Image with WebImage:
<StackLayout class="image-container">
<WebImage [src]="item.images[0].image" stretch="aspectFill" class="image-content-container"></WebImage>
</StackLayout>

OnBlur event without the ngModel & textfield blinking

Nativescript app: I am creating dinamy TextFields.
1) Probme - When i tap on dinamicly generated text field, the keyboard shows for miliseconds and the disapears. When i tap really fast a few times then the keyboard stays.
2) How to make onChange/onBlur event on dinamicly generated TextField? Like when i update the textField i need to call a method.
Here is the current list:
(blur) Does not work:
<StackLayout col="1" row="0">
<ListView [items]="categoryService.attributes | async">
<template let-item="item" let-i="index">
<GridLayout rows="50 100">
<Label [text]="item.name"></Label>
<TextField #input *ngIf="item.type=='text'" row="1" hint="Enter Value here" [text]="item.name" (blur)="categoryService.onAttributeChange(item, item.type, null, input.value)"></ TextField>
<Switch #switch *ngIf="item.type=='checkbox'" row="1" checked="false" (checkedChange)="categoryService.onAttributeChange(item, item.type, null, switch.checked)"></Switch>
<DropDown #aa
*ngIf="item.type=='select'"
row="1"
[items]="categoryService.showAttributeValues(item.value)"
[selectedIndex]="selectedIndex"
(selectedIndexChange)="categoryService.onAttributeChange(item, item.type, aa.selectedIndex)"></DropDown>
</GridLayout>
</template>
</ListView>
</StackLayout>
Thanks!
About your second question you could use textChange method and to return $event as argument this will help you to get text for every TextField individually. You could review the sample code below. About the problem with showing the keyboard, it could be something related with the listview itemTap event. However this problem has been reproduced only on Android and still looking for possible solution.
app.component.html
<StackLayout>
<ListView [items]="myItems" (itemTap)="onItemTap($event)">
<template let-item="item" let-i="index" let-odd="odd" let-even="even">
<StackLayout [class.odd]="odd" [class.even]="even">
<Label [text]='"index: " + i'></Label>
<Label [text]='"[" + item.id +"] " + item.name'></Label>
<TextField (tap)="onTap($event)" hint="Enter text" text="" (textChange)="ontextChange($event)"></TextField>
</StackLayout>
</template>
</ListView>
</StackLayout>
app.component.ts
import {Component, Input, ChangeDetectionStrategy} from '#angular/core';
import {TextField} from "ui/text-field";
import app = require("application");
class DataItem {
constructor(public id: number, public name: string) { }
}
#Component({
selector: "my-app",
templateUrl: "app.component.html",
})
export class AppComponent {
public myItems: Array<DataItem>;
private counter: number;
public status =true;
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;
}
}
public onItemTap(args) {
console.log("------------------------ ItemTapped: " + args.index);
}
public ontextChange(args){
console.log("text "+args.object.text);
}
}
I hope this helps

Resources