nativescript 'this' inside tkListViewHeader (RadListView header directive) - nativescript

I'm using the TKListViewHeaderDirective of teleriks RadListView in nativescript like so:
<GridLayout columns="*" rows="*" tkToggleNavButton>
<RadListView *ngIf="!loading" row="3" col="0" [items]="nodes" ...>
<ng-template tkListItemTemplate let-node="item">
<!-- list item -->
</ng-template>
<ng-template tkListViewHeader>
<GridLayout columns="*" rows="auto, auto, auto">
<GridLayout row="0" col="0" columns="40,*,40">
<Button class="fa action-item" row="0" col="0" [text]="'fa-sort-amount-asc' | fonticon" ios.position="right" android="actionBar" style="background-color:#c9c9ce;;"></Button>
<SearchBar row="0" col="1" #searchInput hint="Search" (submit)="search(searchInput.text)" (clear)="search('')" (textChange)="search(searchInput.text)"></SearchBar>
<Button class="fa action-item" row="0" col="2" [text]="'fa-th' | fonticon" ios.position="right" android="actionBar" style="background-color:#c9c9ce;"></Button>
</GridLayout>
<StackLayout row="1" col="0">
<Label text="Hello world"></Label>
<Label [text]="currentNode.name"></Label>
<Label [text]="nodes?.length ? nodes.length : 0"></Label>
</StackLayout>
<StackLayout row="2" col="0" *ngIf="!nodes?.length" class="list-group">
<!-- some contents -->
</StackLayout>
<StackLayout row="3" col="0" *ngIf="currentNode?.name !== '/'" class="list-group">
<!-- some contents -->
</StackLayout>
</GridLayout>
</ng-template>
</RadListView>
</GridLayout>
it seems like two things go wrong here:
this seems to be missing here (the *ngIf should show one of the StackLayouts in specific cases but does not
The GridLayout (does not have any effect if I change it to StackLayout) inside the list header shows only one child element
According to the docs: http://docs.telerik.com/devtools/nativescript-ui/Controls/Angular/ListView/header-footer

There is an issue on github concerning this: https://github.com/telerik/nativescript-ui-feedback/issues/207

Related

Nativescript AbsoluteLayout, parent position relative

I have an AbsoluteLayout that is supposed to open and go over a mdCardview, but it seems that it is trying to squeeze everything inside the cardview. I tried messing with the CSS position tag, but it doesn't change one bit.
In the picture below you can see the save button which is also an absolutelayout, this one does go over every other component.
This is my TimeCard component which has a button and a absolute layout that would be used as a popup
<template>
<GridLayout class="dialog" rows="*, *" columns="*" :class="{ dialogOpen: dialogOpen }">
<MDButton :text="label" #tap="showDialog()" class="fill" />
<AbsoluteLayout class="dialog-wrapper">
<StackLayout top="100" left="20" class="dialog">
<TimePicker v-bind="$attrs" v-on="$listeners" />
<MDButton text="Confirm" class="cancel" />
<Button class="btn btn-outline" text="Cancel" #tap="closeDialog"></Button>
</StackLayout>
</AbsoluteLayout>
</GridLayout>
</template>
data: () => ({
dialogOpen: false
}),
methods: {
showDialog() {
this.dialogOpen = true
},
closeDialog() {
this.dialogOpen = false
}
}
This is my availabilityCard which contains a slot with the timecard component
<StackLayout >
<MDCardView elevation="5px" ripple="true" width="100%" margin="30px" class="cardview">
<GridLayout rows="*, *" columns="*, *, *" class="card" width="auto">
<StackLayout col="0" row="0">
<Label class="title" :text="getNameAndDayOfMonth(day)" />
</StackLayout>
<MDButton col="2" row="0" text="fill" class="fill" #tap="showActions()" v-if="!show && Object.keys(value).length === 0" />
<GridLayout row="1" colSpan="3" columns="auto, auto, *" rows="*, *" width="auto" v-else>
<GridLayout row="0" columns="auto, auto" rows="*" colSpan="2" width="auto">
<slot />
</GridLayout>
<MDButton text="clear" col="2" row="0" class="cancel" #tap="cancelTime()" />
<template v-if="Object.keys(value).length !== 0">
<Label :text="format(value.start)" col="0" row="1" />
<Label :text="format(value.end)" col="1" row="1" />
</template>
</GridLayout>
</GridLayout>
</MDCardView>
</StackLayout>
This is the parent component availability that defines the timecard component
<StackLayout>
<AvailabilityCard v-for="(day, i) in days" :key="i" v-model="day.element" :day="day.date">
<TimeCard col="0" label="begin" v-model="day.element.start"></TimeCard>
<TimeCard col="1" label="eind" v-model="day.element.end"></TimeCard>
</AvailabilityCard>
</StackLayout>
Availability component screen:

How to fix android ui performance

I'm getting:
Avoid using ListView or ScrollView with no explicit height set inside StackLayout. Doing so might results in poor user interface performance and a poor user experience.
My UI performance is very crappy on Android. It seems pretty smooth on iOS. I'm trying to figure out what could be the issue. This one error crops up for me. I'm running "nativescript-angular": "^8.0.0",
<ScrollView [visibility]="isBusy ? 'collapsed' : 'visible'" #sv>
<GridLayout rows="auto,auto,auto,auto" id="t2" columns="*" class="template_body">
<GridLayout row="0" col="0" #wv1wrapper>
<!-- <web-view id="instruction-wv" #wv1></web-view> -->
<template-text [data]="lessonDetail.instruction" *ngIf="lessonDetail.instruction" [screenwidth]="screenWidth"></template-text>
</GridLayout>
<StackLayout row="1" col="0" class="main-img">
<Image [src]="(lesson$ | async)?.thumbUrl" #imgref [data-image]="(lesson$ | async)?.imageUrl" (tap)="modalImage($event);"></Image>
</StackLayout>
<GridLayout row="2" col="0" #wvwrapper>
<!-- <web-view id="wv" #wv></web-view> -->
<template-text [data]="lessonDetail.body_text" [version]="version" *ngIf="lessonDetail.body_text" [screenwidth]="screenWidth"></template-text>
</GridLayout>
</GridLayout>
This is a template that is pulled into a router-outlet that looks like this in the master template:
<FlexboxLayout class="contentbody" [visibility]="isBusy ? 'hidden' : 'visible'" [data-template]="template_id">
<Label [text]="error" *ngIf="error"></Label>
<router-outlet></router-outlet>
</FlexboxLayout>
Also on that page, I do have a listview inside of a stacklayout.
<StackLayout row="0" >
<StackLayout class="vocab-notes">
<Label *ngIf="vocabArray" class="h3 section-title" text="Vocabulary"></Label>
<ListView [items]="vocabArray" id="vocablistview" (itemTap)="onItemTap($event)" class="list-items">
<ng-template let-item="item" let-i="index" let-odd="odd" let-even="even">
<GridLayout columns="*" rows="auto,auto" [class.odd]="odd" [class.even]="even" class="vocab-list">
<FlexboxLayout col="0" row="0" class="vocab-list-item-layout">
<Label [text]='item.label' textWrap="true" [id]="item.id" class="h3 vocab-list-item" (tap)="showVocab($event)"></Label>
</FlexboxLayout>
</GridLayout>
</ng-template>
</ListView>
</StackLayout>
I know its late for you but if someone is looking for this in future, so if you are getting below in console on any page you load.
JS: Avoid using ListView or ScrollView with no explicit height set inside StackLayout. Doing so might results in poor user interface performance and a poor user experience.
You just need to give your scrollView a height, try different heights like in my case I need 650
<Page class="main" actionBarHidden="true">
<StackLayout class="gradient-bg">
<ScrollView orientation="vertical" height="650"> <!-- Here height is 650 -->
<StackLayout>
<GridLayout rows="50" class="page-header">
<Label
row="0"
class="fa label-back"
:text="'fa-arrow-left' | fonticon"
v-on:tap="navigateTo('app')"
/>
<Label text="Plot Suggestion" row="0" class="lbl-heading" horizontalAlignment="center" />
...
...

What is Repeater.itemsLayout property for? How and in what cases to use it?

This works as expected (without <Repeater.itemsLayout> and wrapped by <StackLayout>):
<GridLayout columns="auto, *" rows="auto">
<Label text="Some Text" row="0" col="0" backgroundColor="orange"/>
<StackLayout row="0" col="1" backgroundColor="green">
<Repeater items="{{ items }}">
<Repeater.itemTemplate>
<Label text="{{ $value }}"/>
</Repeater.itemTemplate>
</Repeater>
</StackLayout>
</GridLayout>
And this as NOT expected (with <Repeater.itemsLayout> and without wrapping by <StackLayout>):
<GridLayout columns="auto, *" rows="auto">
<Label text="Some Text" row="0" col="0" backgroundColor="orange"/>
<Repeater items="{{ items }}">
<Repeater.itemsLayout>
<StackLayout row="0" col="1" backgroundColor="green"/>
</Repeater.itemsLayout>
<Repeater.itemTemplate>
<Label text="{{ $value }}"/>
</Repeater.itemTemplate>
</Repeater>
</GridLayout>
Following code works because you are wrapping your Repeater in StackLayout and assiging it row and column and that is required as well if your putting that inside a GridLayout.
<GridLayout columns="auto, *" rows="auto">
<Label text="Some Text" row="0" col="0" backgroundColor="orange"/>
<StackLayout row="0" col="1" backgroundColor="green">
<Repeater items="{{ items }}">
<Repeater.itemTemplate>
<Label text="{{ $value }}"/>
</Repeater.itemTemplate>
</Repeater>
</StackLayout>
</GridLayout>
If you do not want to wrap inside a StackLayout, you should assign row="0" col="1" to Repeater.
Now comes to your question, that use of Repeater.itemsLayout, it gets or set the items layout of the Repeater. Default value is StackLayout with orientation="vertical".
So if you have a usecase where you want all the items in Repeater align horizontally, you should use following code.
<ScrollView row="0" col="0" orientation="horizontal">
<Repeater items="{{ items }}">
<Repeater.itemsLayout>
<StackLayout orientation="horizontal" />
</Repeater.itemsLayout>
<Repeater.itemTemplate>
<Label text="{{ $value }}" />
</Repeater.itemTemplate>
</Repeater>
</ScrollView>
We can set row and col properties for Repeater tag. Like so:
<GridLayout columns="auto, *" rows="auto, *">
<Label text="Some Text" row="0" col="0"/>
<Repeater row="1" items="{{ items }}">
<Repeater.itemsLayout>
<StackLayout orientation="horizontal" />
</Repeater.itemsLayout>
<Repeater.itemTemplate>
<Label text="{{ $value }}"/>
</Repeater.itemTemplate>
</Repeater>
</GridLayout>
Answer can be found here: https://github.com/NativeScript/NativeScript/issues/6554#issuecomment-438167999

How can I make a StackLayout with ngFor loop into scrollable list?

<StackLayout width="100%" *ngFor="let item of (videos$ | async)">
<CardView class="studentCard" margin="2" elevation="10" radius="1">
<GridLayout rows="auto, auto, auto" columns="auto, auto, *">
<Image [src]="item.snippet.thumbnails.high.url" stretch="aspectFill" colSpan="3" row="0"></Image>
<Label [text]="item.snippet.channelTitle" textWrap="true" row="2" colSpan="1" ></Label>
<Label [text]="item.snippet.title" textWrap="true" row="2" col="1" colSpan="2" >></Label>
</GridLayout>
</CardView>
</StackLayout>
I tried to wrap it in ScrollView, didn't work.
I couldn't make (items$ | async) work with ListView either, seems ngFor can't work with ListView, we need ng-template for ListView.
I tried the following but only the first item is rendering
<ScrollView>
<ListView [items]="videos$ | async" class="list-group">
<ng-template let-item="item">
<GridLayout class="list-group-item">
<Image [src]="item.snippet.thumbnails.high.url"></Image>
<Label [text]="item.snippet.channelTitle" ></Label>
<Label [text]="item.snippet.title">></Label>
</GridLayout>
</ng-template>
</ListView>
</ScrollView>
Wraping the entire code first with StackLayout then with ScrollView worked
<ScrollView>
<StackLayout>
<StackLayout width="100%" *ngFor="let item of (videos$ | async)">
<CardView class="studentCard" margin="2" elevation="10" radius="1">
<GridLayout rows="auto, auto, auto" columns="auto, auto, *">
<Image [src]="item.snippet.thumbnails.high.url" stretch="aspectFill" colSpan="3" row="0"></Image>
<Label [text]="item.snippet.channelTitle" textWrap="true" row="2" colSpan="1" ></Label>
<Label [text]="item.snippet.title" textWrap="true" row="2" col="1" colSpan="2" >></Label>
</GridLayout>
</CardView>
</StackLayout>
</StackLayout>
</ScrollView>

Very strange behaviour when trying to replicate a table using a Listview and GridLayout

I am trying to replicate a table using a ListView. Displaying the table's cell content works fine but when I add another GridLayout wrapped in a StackLayout above the Listview the Listview doesn't get displayed at all... Any idea why this might be happening? I tried as well to add the table headers to the ListView using nsTemplateKey but still get the same issue where the headers show but no table body content. When I remove the top GridLayout containing the headers the Listview's content displays perfectly as it should for some reason...
my code:
//headers
<StackLayout class="m-b-10">
<GridLayout rows="*" columns="*, *, *" *ngIf="stockTakeDetailList.length > 0 && !product">
<Label row="0" col="0" text="Name"></Label>
<Label row="0" col="1" text="Qty"></Label>
<Label row="0" col="2" text="Action"></Label>
</GridLayout>
</StackLayout>
//listview containing the table body
<StackLayout *ngIf="stockTakeDetailList.length > 0 && !product">
<ListView [items]="stockTakeDetailList">
<template let-captureItem="item" let-i="index">
<GridLayout rows="*" columns="*, *, *">
<Label row="0" col="0" class="list-group-item" textWrap="true" [text]="captureItem.ProductDetail_Name"></Label>
<Label row="0" col="1" class="list-group-item" [text]="captureItem.Qty"></Label>
<Label row="0" col="2" class="list-group-item font-awesome" text="" (tap)="removeCaptureItem(i)"></Label>
</GridLayout>
</template>
</ListView>
</StackLayout>
Try encapsulating all of the code within a StackLayout:
<StackLayout>
<StackLayout class="m-b-10">
<GridLayout rows="*" columns="*, *, *" *ngIf="stockTakeDetailList.length > 0 && !product">
<Label row="0" col="0" text="Name"></Label>
<Label row="0" col="1" text="Qty"></Label>
<Label row="0" col="2" text="Action"></Label>
</GridLayout>
</StackLayout>
<StackLayout *ngIf="stockTakeDetailList.length > 0 && !product">
<ListView [items]="stockTakeDetailList">
<template let-captureItem="item" let-i="index">
<GridLayout rows="*" columns="*, *, *">
<Label row="0" col="0" class="list-group-item" textWrap="true" [text]="captureItem.ProductDetail_Name"></Label>
<Label row="0" col="1" class="list-group-item" [text]="captureItem.Qty"></Label>
<Label row="0" col="2" class="list-group-item font-awesome" text="" (tap)="removeCaptureItem(i)"></Label>
</GridLayout>
</template>
</ListView>
</StackLayout>
</StackLayout>
Maybe try without the extra stack layouts:
<StackLayout>
<StackLayout class="m-b-10">
<GridLayout rows="*" columns="*, *, *" *ngIf="stockTakeDetailList.length > 0 && !product">
<Label row="0" col="0" text="Name"></Label>
<Label row="0" col="1" text="Qty"></Label>
<Label row="0" col="2" text="Action"></Label>
</GridLayout>
</StackLayout>
<ListView [items]="stockTakeDetailList" *ngIf="stockTakeDetailList.length > 0 && !product">
<template let-captureItem="item" let-i="index">
<GridLayout rows="*" columns="*, *, *">
<Label row="0" col="0" class="list-group-item" textWrap="true" [text]="captureItem.ProductDetail_Name"></Label>
<Label row="0" col="1" class="list-group-item" [text]="captureItem.Qty"></Label>
<Label row="0" col="2" class="list-group-item font-awesome" text="" (tap)="removeCaptureItem(i)"></Label>
</GridLayout>
</template>
</ListView>
</StackLayout>

Resources