Nativscript platform specific template not working - nativescript

Building an app in Nativescript 5.0 for both Android and iOS. For some reason the and tags don't seem to work as they should, or i might be doing it wrong.
<StackLayout>
<android>
<ActionBar class="header" flat="true">
<StackLayout orientation="vertical">
<app-eon-colors-top></app-eon-colors-top>
<GridLayout columns="auto, *, auto, auto" rows="2*">
<Label class="title" col="0" text="{{title}}" verticalAlignment="center"></Label>
<Label class="icon fa-solid" col="2" text="" verticalAlignment="center"></Label>
<Label class="logout fa-solid" col="3" row="0" text="Logga ut" verticalAlignment="center" (tap)="logout()"></Label>
</GridLayout>
</StackLayout>
</ActionBar>
</android>
<ios>
<ActionBar class="header" flat="false">
<StackLayout orientation="horizontal">
<Label class="title" text="{{title}}"></Label>
</StackLayout>
<ActionItem ios.position="right">
<StackLayout orientation="horizontal">
<Label class="icon fa-solid" text=""></Label>
<Label class="logout fa-solid" ios.position="right" text="Logga ut" (tap)="logout()"></Label>
</StackLayout>
</ActionItem>
</ActionBar>
</ios>
</StackLayout>
When running this template on android it only uses the code in the ios block, but on ios it seems to work fine.

That's NativeScript Core way of writing platform specific XML. With Angular, you could use directives, there is a Github issue that discusses about this problem and also provides sample code to implement this platform specific directive on your project.
Platform specific structural directive
import { Directive, ViewContainerRef, TemplateRef, Inject } from "#angular/core";
import { DEVICE } from "nativescript-angular/platform-providers";
import { Device, platformNames } from "platform";
#Directive({
selector: "[appIfAndroid]"
})
export class IfAndroidDirective {
constructor( #Inject(DEVICE) device: Device, container: ViewContainerRef, templateRef: TemplateRef<Object>) {
if (device.os === platformNames.android) {
container.createEmbeddedView(templateRef);
}
}
}
#Directive({
selector: "[appIfIos]"
})
export class IfIosDirective {
constructor( #Inject(DEVICE) device: Device, container: ViewContainerRef, templateRef: TemplateRef<Object>) {
if (device.os === platformNames.ios) {
container.createEmbeddedView(templateRef);
}
}
}
Once you import this directive in your module, then you could use *appIfAndroid / *appIfIos on any tag.

Related

How do I show through *ngIf

I want to trigger the *ngIf function through my home.component.ts.
html
<GridLayout class="page">
<GridLayout row="0" rows="*, 2*, *">
<GridLayout width="57%" row="0" horizontalAlignment="center" verticalAlignment="center">
<button (click)="test()" text="testbutton"></button>
</GridLayout>
<GridLayout class="carousel-item-circle" row="1" horizontalAlignment="center" verticalAlignment="center">
<label class="fa carousel-item-icon" text="" textWrap="true"></label>
</GridLayout>
<GridLayout *ngIf="testi" width="49%" row="2" horizontalAlignment="center" verticalAlignment="center">
<Label class="text-color-blue opensans-regular carousel-item-desc" text="Mikrofon zum Sprechen antippen." textWrap="true"></Label>
</GridLayout>
</GridLayout>
ts
public vibrator = new Vibrate();
public testi = true;
constructor(private page: Page) {
// Use the component constructor to inject providers.
}
ngOnInit(): void {
this.page.actionBarHidden = true;
this.page.addCss(".page-content { background: #000000");
}
vibrate(){
this.vibrator.vibrate(2000);
}
test(){
this.testi = !this.testi;
}
It seems so simple but it doesnt work.
Is there something i missed?
You need to make the variable true/false on click
Write in Your HTML file
<button (click)="test()">Click</button>
<span *ngIf="testi">NG IF</span>
Write in Your TS file
First Declare testi as
testi = false
test(){
testi = true;
}
Using *ngIf you can show the element whenever it is true or not empty, if it is false or empty then it will not display element in browser
Hope this will solve your problem, Thanks
NativeScript Button uses tap not click. So in your code test() is never called.
<button (tap)="test()" text="testbutton"></button>
Refer the getting started guide and go through the available UI components to understand the core differences.

builder.parse() with bindingContext

I have the following code:
private loadSlides(): Promise<any> {
return new Promise((resolve, reject) => {
const component = builder.parse(slideTemplate);
component.bindingContext = {
content: 'HHAHAAHA'
};
resolve(component);
});
}
and this is the value for slideTemplate:
export const slideTemplate: string = `
<GridLayout row="0" rows="*, 2*, *">
<GridLayout width="57%" row="0" horizontalAlignment="center" verticalAlignment="center">
<Label class="lobster-regular carousel-item-head" [text]="content" textWrap="true"></Label>
</GridLayout>
</GridLayout>
`;
Now when I bind the value from my template it only shows empty string.
Why is that so?
You can not use Angular template / binding syntax with builder.parse(...), it's created outside Angular context.
Since you are using bindingContext which is NativeScript Core way of handling data binding, you should use text="{{ content }}"
export const slideTemplate: string = `
<GridLayout row="0" rows="*, 2*, *">
<GridLayout width="57%" row="0" horizontalAlignment="center" verticalAlignment="center">
<Label class="lobster-regular carousel-item-head" text="{{ content }}" textWrap="true"></Label>
</GridLayout>
</GridLayout>
`;
I'm unsure why you may need builder here, I would suggest sticking with Angular components if possible.

nativescript bottom nav that stays in place after loading new view

I'm developing some app made on nativescript. Recently, i see that my app is more like website not an app, beacuse of how navigation works.
I'm having bottom nav (atached - this grey with 5 icons) that is used to load proper views.
But when i click on home or any other icon, new view is loaded, but also nav is 'reloaded'. So it will not stay in place but load with new view. My question is - is possible oto have static botom bar ? I've tried 2 plugins found on marketplace, but without success. Thanks for and help.
<Page class="page" loaded="loaded" xmlns:header="components/header" xmlns:footer="components/footer">
<GridLayout rows="120,*,60">
<StackLayout row="0">
<!-- Common header -->
<header:header/>
</StackLayout>
<ScrollView row="1" verticalAlignment="top" class="scrollview" tap="{{ loadPage }}">
<StackLayout class="redeem">
<Label text="Enter your code below to redeem your reward" class="info" textWrap="true"></Label>
<Label text="Code" class="info code" textWrap="true"></Label>
<TextField />
<Button text="Redeem" class="button blue"></Button>
</StackLayout>
</ScrollView>
<StackLayout row="2">
<!-- Common footer -->
<footer:footer/>
</StackLayout>
</GridLayout>
</Page>
:
<AbsoluteLayout class="footer" loaded="menu" horizontalAlignment="center" xmlns:sd="nativescript-ui-sidedrawer">
<GridLayout rows="auto" columns="*,*,*,*,*" horizontalAlignment="center">
<Label row="0" col="0" class="fa" text="" tap="{{ mainPage }}"></Label>
<Label row="0" col="1" class="fa" text="" tap="{{ creditPage }}"></Label>
<Label row="0" col="2" class="fa" text="" tap="{{ seatPage }}"></Label>
<Label row="0" col="3" class="fa" text="" tap="{{ refs }}"></Label>
<Label id="openMenu" row="0" col="4" class="fa" text="" tap="toggleDrawer"></Label>
<!--<Label id="openMenu" row="0" col="4" class="fa" text="" tap="{{ loadPage }}"></Label>-->
</GridLayout>
</AbsoluteLayout>
You could use DockLayout and dock the content to the bottom (Angular example here)
Also in the upcoming release 4.0.0 of NativeScript (expected April-2018) will provide support for different root views (apart from Page) meaning you could create bottom static layout like GridLayout or even better a bottom TabView (also coming for Android in 4.0.0) and create Frame in the upper layout for your dynamic content. (Look here)

ListView issue with Angular2 final

We use NativeScript 2.3 with Angular2 final.
We have an issue with the ListView component. We can bind something to the view but it always display this:
Here's the code of the template:
`
<GridLayout row="0" columns="*, auto" class="add-bar">
<!--<TextField #groceryTextField [(ngModel)]="grocery" hint="Enter a grocery item" col="0"></TextField>-->
<!--<Image src="res://add" (tap)="add()" col="1"></Image>-->
</GridLayout>
<ListView [items]="orderForms" row="1" class="small-spacing" [class.visible]="listLoaded">
<template let-item="item">
<GridLayout columns="*, auto">
<Label col="0" [text]="item.frameworkContractNumber" class="medium-spacing"></Label>
<Label col="1" [text]="item.requestIdentifier" class="medium-spacing"></Label>
</GridLayout>
</template>
</ListView>
With the previous RC of angular it was working. Now whatever we try(array, observables, ...) we end up with this. It's the same on Android and IOS.
Any ideas?

Binding Context not working Nativescript

there is no error in console, I've tried many things but cannot understand the actual problem with code. Can anybody help me in this.. and emulator snippets and code below:
home.ts:
enter code here
import {EventData,Observable} from "data/observable";
import {Page} from "ui/page";
var page : Page;
var tempSessions = [
{
id:"0",
title:"session 0"
},{
id:"1",
title:"session 1"
},{
id:"2",
title:"session 2"
}];
export function pageLoaded(args:EventData) {
page = <Page>args.object;
page.bindingContext = new Observable({
sessions:tempSessions
});
}
home.xml:
<Page xmlns="http://schemas.nativescript.org/tns.xsd" load="pageLoaded">
<GridLayout rows="auto,*">
<!--row 0-->
<StackLayout></StackLayout>
<!--row 1-->
<GridLayout rows="auto,*" row="1">
<ListView items="{{ sessions }}">
<ListView.itemTemplate>
<Label text="item"/>
</ListView.itemTemplate>
</ListView>
</GridLayout>
</GridLayout>
</Page>
emulator
I found several issues in your code. The first one is that the page event is called loaded instead load. The second one is that you could use ObservableArray Module, which would auto update the ListView when you push new item in the array. You could review the NativeScript Getting Started Guide
main-page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded">
<GridLayout rows="auto,*">
<!--row 0-->
<StackLayout row="0">
<Label text="sample text" textWrap="true" />
</StackLayout>
<!--row 1-->
<GridLayout rows="*" row="1">
<ListView row="0" items="{{ sessions }}">
<ListView.itemTemplate>
<StackLayout>
<Label text="{{title}}"/>
</StackLayout>
</ListView.itemTemplate>
</ListView>
</GridLayout>
</GridLayout>
</Page>
main-page.ts
import {EventData,Observable} from "data/observable";
import {ObservableArray} from "data/observable-array";
import {Page} from "ui/page";
var page : Page;
var tempSessions = new ObservableArray();
export function pageLoaded(args:EventData) {
tempSessions.push({
id:"0",
title:"session 0"
});
tempSessions.push({
id:"1",
title:"session 1"
});
tempSessions.push({
id:"2",
title:"session 2"
});
page = <Page>args.object;
page.bindingContext = new Observable({
sessions:tempSessions
});
}

Resources