Binding Context not working Nativescript - 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
});
}

Related

Multiple fullscreen in scrollview with Nativescript

I would like to know how can I have multiple fullscreen in scrollview with nativescript please ?
I tried this :
<Page actionBarHidden="true" class="page">
<ScrollView orientation="vertical">
<StackLayout>
<StackLayout height="100%" backgroundColor="red">
<Label text="Fullscreen 1"></Label>
</StackLayout>
<StackLayout height="100%" backgroundColor="blue">
<Label text="Fullscreen 2"></Label>
</StackLayout>
</StackLayout>
</ScrollView>
</Page>
But the stack aren't fullscreen.
I fixed with this :
Template
<Page actionBarHidden="true">
<ScrollView orientation="vertical">
<StackLayout>
<StackLayout :height="screenHeight" backgroundColor="red">
...
</StackLayout>
<StackLayout :height="screenHeight" backgroundColor="blue">
...
</StackLayout>
</StackLayout>
</ScrollView>
</Page>
And add this :
import { screen } from "tns-core-modules/platform";
...
data() {
return {
screenHeight: 0
};
},
...
created() {
this.screenHeight = screen.mainScreen.heightDIPs
}

Nativescript-Vue ScrollView scrollable height is always 0. My goal is to scroll it to bottom since it's a Chat App

In my Nativescript-Vue application, I have a ListView within a ScrollView, defined as such:
<Page>
<ActionBar :title="friend.name">
<NavigationButton text="Go Back" android.systemIcon="ic_menu_back" #tap="$navigateBack"/>
</ActionBar>
<ActivityIndicator busy="true" v-if="isLoading" />
<StackLayout v-else orientation="vertical" >
<ScrollView ref="scrollLayout" class="scrollLayout" height="90%" orientation="vertical">
<ListView minHeight="90%" ref="listLayout" class="listLayout" for="item in conversations">
<v-template>
<GridLayout columns="*" rows="auto" class="msg">
<StackLayout :class="currentUser.id == item.user_id? 'me' : 'them'" orientation="horizontal" :horizontalAlignment="currentUser.id == item.user_id? 'right' : 'left'">
<Label :text="item.chat" class="msg_text" textWrap="true" verticalAlignment="top" />
</StackLayout>
</GridLayout>
</v-template>
</ListView>
</ScrollView>
<StackLayout height="10%" class="chat-box">
<GridLayout columns="*,auto" style="padding: 5" verticalAlignment="center">
<TextField hint="Enter message..." class="chatTextField" row="0" col="0" v-model="message"></TextField>
<Button row="0" col="1" text="send" #tap="scollToBottom"></Button>
</GridLayout>
</StackLayout>
</StackLayout>
</Page>
I already looked into this question by adding minHeight but it does not work on my case.
This is the method code to scroll to bottom but the scrollableHeight is always 0
scollToBottom() {
this.scrollLayout.nativeView.scrollToVerticalOffset(this.scrollLayout.nativeView.scrollableHeight, false);
console.log(this.$refs.scrollLayout.nativeView.scrollableHeight)
},
Hello I found a solution for this. I use ListView to scroll to the latest chat by using this code: Based on this [link]: https://docs.nativescript.org/vuejs/ns-ui/ListView/scrolling
scollToBottom () {
// in order to avoid race conditions (only on iOS),
// in which the UI may not be completely updated here
// we use this.$nextTick call
this.$nextTick(() => {
const indexToScroll = this.conversations.length - 1;
console.log('Programmatic scrolling to ' + this.conversations[indexToScroll].chat + '... ');
this.$refs.listLayout.nativeView.scrollToIndex(indexToScroll, false);
});
},
That's what I've implemented in my app which is not ideal but it works. I had to add a setTimeout for it to scroll. The messages are again wrapped in a Scroll View:
scrollToBottom() {
setTimeout(() => {
let scroll = this.$refs.scrollLayout.nativeView.scrollableHeight //get the height of the scroll area
console.log("Height changed " + scroll)
this.$refs.scrollLayout.nativeView.scrollToVerticalOffset(scroll, false) //scroll to the last message
}, 1000)
}

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.

Setting CSS class from data in ObservableArray

I have an observable array that contains some info. I'm looking to dynamically change the class based on the data contained within the array. I've tried:
#js
var pageData = new Observable({
locations: new ObservableArray([
{location: 'OR1'},
{location: 'OR2'},
{location: 'OR3'},
{location: 'WR1'},
{location: 'PO1'}
]),
surgeons: new ObservableArray([
{surgeon: 'Dr. Pepper', selected_text: '', selected_class: ''},
{surgeon: 'Dr. Scholls', selected_text: "\uf111", selected_class: 'font-awesome'}
])
});
exports.loaded = function(args) {
var page = args.object;
page.bindingContext = pageData;
};
#xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="onNavigatingTo" xmlns:statusBar="nativescript-statusbar"
class="green" loaded="loaded">
<GridLayout orientation="vertical" columns="*" rows="2*,*,3*,*,5*,*">
<Label text="mrn: 123456" row="0" class="h1" horizontalAlignment="center"/>
<Label text="Surgeon" class="h3" row="1"/>
<ListView col="0" row="2" items="{{ surgeons }}" separatorColor="#58847D" class="margin-sides-10 rounded-corners-all">
<ListView.itemTemplate>
<GridLayout orientation="vertical" columns="75,*" rows="*">
<Label text="{{ selected_text }}" class="{{ selected_class}} black-text" col="0"/>
<Label text="{{ surgeon }}" class="black-text" col="1"/>
</GridLayout>
</ListView.itemTemplate>
</ListView>
<Label text="Location" class="h3" row="3"/>
<ListView col="0" row="4" items="{{ locations }}" separatorColor="#58847D" class="margin-sides-10 rounded-corners-all">
<ListView.itemTemplate>
<Label text="{{ location }}" class="black-text"/>
</ListView.itemTemplate>
</ListView>
<Button text="Save" class="dark-grey margin-top-10" row="5" tap="save"/>
</GridLayout>
What is the best way to conditionally style individual components?
Actually the reason it isn't working is because you have a simple mistake in your XML. Your xml needs to be:
<Label text="{{ selected_text }}" class="{{selected_class}}" col="0"/>
You cannot mix both observable code and non observable code in the same element property. By you adding the "black-text" to the class property; then NativeScript would have treated it as a literal class named .{{selected_class}} and .black-text.

Resources