I am working with Nativescript ListView and have 4 arrays.
//name array
for (var i = 0; i < employeesJson2.length; i++) {
empNameArray.push(employeesJson2[i].Name)
}
// image array
for (var i = 0; i < employeesJson2.length; i++) {
empImageArray.push(employeesJson2[i].Image)
}
// phone array
for (var i = 0; i < employeesJson2.length; i++) {
empPhoneArray.push(employeesJson2[i].Phone)
}
// email array
for (var i = 0; i < employeesJson2.length; i++) {
empEmailArray.push(employeesJson2[i].Email)
}
I need to be able to utilize these 4 arrays in 1 listview row.
Currently I just have
<StackLayout orientation="vertical">
<ListView items="{{ empNameArray }}" id="rolePicker" itemTap="listViewRoleTap" style="text-align: center" rowHeight="50">
<ListView.itemTemplate>
<Label text="{{ $value }}" textWrap="true" style="padding-top: 10; font-size: 19" />
</ListView.itemTemplate>
</ListView>
</StackLayout>
If i add another listview item it doesn't display. Ideally the items would show up in the same row side by side. Am i missing a step? Should I be combining the arrays? If so, How?
Each list view template can only have one root element. That said if you want to visualize, let's say two or three labels, then you will need to wrap then in container layout.
e.g.
<ListView.itemTemplate>
<StackLayout>
<Label text="first label" />
<Label text="{{ $value }}" />
<Label text="third label" />
</StackLayout>
</ListView.itemTemplate>
Another thing - why iterating over one array to create four additional arrays? If your business logic allows then you can simply use the array with your JSON objects to populate your list view.
What $value is providing is an easy way to bind to value that is not a complex object like a string. So if your array items was of the following kind
var myArray = ["ab", "cd", "ef"];
Then you can use $value like in your example to render each of the value of the current item.
e.g.
<ListView items="{{ myArray }}">
<ListView.itemTemplate>
<Label text="{{ $value }}" />
</ListView.itemTemplate>
</ListView>
However, as far as I understand in your case the objects are of the following kind:
var myArrayItem = { "name": "John",
"image": "some-image-path",
"phone": 123456,
"email": "abv#xyz.com" };
So if you want to iterate and visualize your different key-values then you can do it accessing the key in your binding e.g.
<ListView items="{{ employeesJson2 }}">
<ListView.itemTemplate>
<StackLayout>
<Label text="{{ name }}" />
<Image src="{{ image }}" />
<Label text="{{ phone }}" />
<Label text="{{ email }}" />
</StackLayout>
</ListView.itemTemplate>
</ListView>
Related
I have this xaml class:
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
HeightRequest="130"
WidthRequest="90"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="InteriorCircle.Pages.MainMenu.CV_PinStyle">
<ContentView.Content>
<StackLayout BackgroundColor="Transparent">
<Frame
HeightRequest="130"
WidthRequest="90"
VerticalOptions="Start"
HasShadow="False"
HorizontalOptions="Start"
BackgroundColor="#565656"
Padding="0"
CornerRadius="25"
IsClippedToBounds="true">
<StackLayout Padding="5">
<Grid VerticalOptions="Center" Margin="10,10,0,0" HorizontalOptions="Center">
<Image x:Name="img_pic"
Margin="3,0,0,0"
HorizontalOptions="Center"
VerticalOptions="Center">
<Image.Clip>
<EllipseGeometry
Center="27,27"
RadiusX="27"
RadiusY="27"/>
</Image.Clip>
</Image>
<Ellipse Stroke="#60CED3"
StrokeThickness="6"
WidthRequest="60"
HeightRequest="60"
HorizontalOptions="Start" />
</Grid>
<Label
Margin="0,0,0,0"
x:Name="label_title"
TextColor="White"
LineBreakMode="TailTruncation"
FontFamily="JakartaReg"
VerticalOptions="Start"
FontSize="12"
HorizontalOptions="Center"/>
<Label
x:Name="label_price"
TextColor="White"
FontFamily="JakartaBold"
VerticalOptions="Start"
FontSize="10"
HorizontalOptions="Center"/>
</StackLayout>
</Frame>
</StackLayout>
</ContentView.Content>
</ContentView>
I retrieve content from another class (event) and set it to the properties from here:
private async Task SetContent(EventType events)
{
InitializeComponent();
byte[] bt = Converters.StringToByteArray(events.eventPictureThumb);
label_title.Text = events.name;
label_price.Text = Converters.GetDecimalPriceFromCents(events.priceInCents) + " €";
Device.BeginInvokeOnMainThread(() =>
{
var source = Converters.ReturnImageSourceFromString(Converters.ByteArrayToString(bt));
img_pic.Source = source;
});
}
However, this does not work sometimes on Android, on iOS not at all.
When I set an image directly in xaml, it is always displayed. On iOS, when the image comes from code, it is never displayed. On Android, it is displayed most of the times, but fails sometimes. When multiple objects load into the view the old ones lose their images.
I am adding the view like so:
var startPin = BitmapDescriptorFactory.FromView(new CV_PinStyle(currentEvent));
Pin pin = new Pin
{
Label = currentEvent.name,
Tag = currentEvent.tblEventID+Constants.DELIMITER+currentEvent.userID,
Icon = startPin,
Type = PinType.Place,
Position = position
};
gMap?.Pins?.Add(pin);
So I am doing somethign wrong here,
can you help me?
I'm completely new to NativeScript but it looks like a sweet platform. I'm writing a toy app and below is my setup:
//code behind
import {AddExpenseModel} from "./add-expense-view-model";
import {EventData} from "tns-core-modules/data/observable";
import {Page} from "tns-core-modules/ui/page";
let expenseModel = new AddExpenseModel();
export function navigatingTo(args: EventData) {
let page = <Page>args.object;
let textField = page.getViewById("tags");
textField.on("textChange", (ev)=>{expenseModel.onTagsTextFieldChange(ev)});
page.bindingContext = expenseModel;
}
export function submit() {
expenseModel.createNewExpense()
}
//view-model
import {Observable, PropertyChangeData} from "tns-core-modules/data/observable";
import {ObservableArray} from "tns-core-modules/data/observable-array";
let u = require('underscore');
export class AddExpenseModel extends Observable {
...
public parsed_tags;
constructor() {
super();
this.parsed_tags = new ObservableArray([]);
...
}
public onTagsTextFieldChange(ev) {
let that = this;
// empty
u.forEach(u.range(this.parsed_tags.length), function (_) {
that.parsed_tags.pop()
});
let parsed = this.parseTags(ev.value);
u.forEach(parsed, function (el) {
that.parsed_tags.push(el);
});
}
private getParsedTags() {
//unbox
return u.map(this.parsed_tags, (el: string) => el)
}
private parseTags(tag_string) {
let arr = u.map(tag_string.split(','), (tag: string) => tag.trim().toLocaleLowerCase());
arr = u.uniq(arr);
arr = u.filter(arr, u.negate(u.isEmpty))
return arr;
}
}
//view
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
<StackLayout class="p-20">
<Label text="Add new expense"/>
<text-field
id="name" text="{{ name }}"
row="0"/>
<text-field id="amount" stext="{{ amount, amount | numberConverter }}" />
<text-field id="tags" secure="false" text="{{ tags }}"
/>
<WrapLayout orientation="horizontal" height="300" width="300">
<ListView items="{{ parsed_tags }}">
<ListView.itemsLayout>
<Label text="{{ $value }}" width="70" backgroundColor="red"/>
</ListView.itemsLayout>
</ListView>
</WrapLayout>
<button text="Add expense" id="submit-button" tap="submit"/>
</StackLayout>
</Page>
What I want to achieve is that when a user writes in the tags textfield, stylised Labels appear in the WrapLayout. This works, however, the Labels appear always stacked vertically. Here's a screenshot
I tried to move the whole WrapLayout section out of the StackedLayout section, but I get a cannot read property 'on' of undefined, undefined.
Putting Labels inside of WrapLayout not within a ListView (i.e. static) works as expected, which makes me thing I probably misuse either the ListView or the WrapLayout. Any directions will be appreciated :)
Cheers
Update
Following Eddy's advice I used a Repeater. Using the following xml
<Repeater items="{{ parsed_tags }}">
<Repeater.itemsLayout>
<WrapLayout orientation="horizontal" backgroundColor="#d3d3d3"/>
</Repeater.itemsLayout>
<Repeater.itemTemplate>
<Label text="{{ $value }}" backgroundColor="#84ddff" marginRight="5" marginLeft="5"/>
</Repeater.itemTemplate>
</Repeater>
correctly produces this:
I still don't see why using a ListView wouldn't work. I used the debugger from Sidekick and this is what I see.
<ListView items="{{ parsed_tags }}">
<ListView.itemsLayout>
<WrapLayout orientation="horizontal" backgroundColor="#d3d3d3" marginRight="5" marginLeft="5"/>
</ListView.itemsLayout>
<ListView.itemTemplate>
<Label text="{{ $value }}" backgroundColor="#84ddff" marginRight="5" marginLeft="5"/>
</ListView.itemTemplate>
</ListView>
I want to create a list view NativeScript with custom item view. I'm using GridLayout to do that.
The problem is: There is large space between rows item.
These are what I've done:
XML:
<Page loaded="loaded">
<ActionBar title="Welcome">
<android>
<NavigationButton android.systemIcon="ic_menu_emoticons" icon="res://icon" tap="showSlideout"/>
</android>
</ActionBar>
<ListView items="{{ items }}">
<ListView.itemTemplate>
<GridLayout rows="auto" columns="auto,*" class="threads-list-wrapper" height="100">
<Image row="0" col="0" src="{{ photo }}"></Image>
<StackLayout row="0" col="1" class="" orientation="vertical">
<Label class="h1" text="{{title}}"></Label>
<Label text="{{ body }}"></Label>
<Label text="{{ date }}"></Label>
</StackLayout>
</GridLayout>
</ListView.itemTemplate>
</ListView>
CSS
.threads-list-wrapper {
padding: 15;
}
.threads-list-wrapper > Image {
height: 64;
width: 64;
margin-right: 15;
}
CODE:
var observableModule = require("data/observable");
var model = new observableModule.Observable();
exports.loaded = function (args) {
var items = [
{
photo: 'res://icon',
title: 'Ardiansyah Putra',
body: 'Ini adalah pesan yang saya kirimkan kepada anda, mohon cepat dibalas ya',
date: 'Just Now'
},
{
photo: 'res://icon',
title: 'Bagus Putra',
body: 'Ini adalah pesan yang saya kirimkan kepada anda, mohon cepat dibalas ya',
date: '12 Jan'
}
];
var page = args.object;
model.set("items", items);
page.bindingContext = model;
};
RESULT:
Not sure what exactly is causing the white space in your case , but here is a snippet where after stripping all the CSS there are no extra white spaces generated in the list-view template.
<GridLayout rows="*" columns="*, *">
<Image col="0" src="res://icon" stretch="none" />
<StackLayout col="1" >
<Label class="h1" text="{{title}}"></Label>
<Label text="{{ body }}"></Label>
<Label text="{{ date }}"></Label>
</StackLayout>
</GridLayout>
I want to get a Level text when the listview (i.e,that level) is tapped.I'm able to get the index of that level.But I can not get the level text field.
View:
<Page loaded="loaded">
<GridLayout>
<ListView items="{{ categoryList }}" itemTap="brand">
<ListView.itemTemplate>
<Label text="{{ category }}" horizontalAlignment="left" verticalAlignment="center" />
</ListView.itemTemplate>
</ListView>
</GridLayout>
</Page>
Js Controller:
function getBrand() {
user.register();
}
exports.brand=function (args){
item=args.index;
//what to put here to be able to get the level text property
user.register(item);
}
Edited: You can put the tap listener to the label inside and get the reference through args:
In XML:
<ListView items="{{ categoryList }}">
<ListView.itemTemplate>
<Label text="{{ category }}" tap="brand"/>
</ListView.itemTemplate>
</ListView>
Then in js:
exports.brand = function(args) {
item = args.object;
var text = item.text;
}
i want to show number or date from bindingcontex array. with this code :
<ListView items="{{ pakets }}" itemTap="onTap">
<ListView.itemTemplate>
<grid-layout rows="220, *, *, *" columns="*" id="cardReport" tap="goReport">
<image row="0" src="{{ foto }}" stretch="aspectFill"/>
<Label row="1" text="{{ textValue }}" />
<Label row="2" text="{{ numberValue }}" />
<Label row="3" text="{{ dateValue }}" />
</grid-layout>
</ListView.itemTemplate>
</ListView>
array pakets fron JSON with value textValue = 'XXXX', numberValue = 3000, dateValue = '2016-06-04'
Both of numberValue and dateValue not show, but textValue show to screen.
What the problems about it ? How to use namber or date in Label Nativescript.
Thanks anyway
I tested this in a test app; and I have the following code, pretty close to unmodified:
Here is the XML:
<Page id="Page" onloaded="pageLoaded" class="">
<ListView items="{{ pakets }}" itemTap="onTap">
<ListView.itemTemplate>
<grid-layout rows="220, *, *, *" columns="*" id="cardReport" tap="goReport">
<image row="0" src="{{ foto }}" stretch="fill"/>
<Label row="1" text="{{ textValue }}" />
<Label row="2" text="{{ numberValue }}" />
<Label row="3" text="{{ dateValue }}" />
</grid-layout>
</ListView.itemTemplate>
</ListView>
</Page>
Here is the JavaScript:
var Observable = require('data/observable').Observable;
var myData = new Observable();
exports.pageLoaded = function(args) {
var page = args.object;
myData.pakets = [
{foto: '~/SO587/nslogo.png', textValue: 'Text', numberValue: 2330, dateValue: '2016-01-01'},
{foto: '~/SO587/gswn.png', textValue: 'Text', numberValue: 2230, dateValue: new Date()},
];
page.bindingContext = myData;
};
And here is how it looks: As you can see from the above data, I have Text, number, Text Date and the second data line has Text, number and a real Date field.
Problems on CSS. i am add with this :
label {
font-family: 'Roboto', Roboto;
}
And work weel.
Thanks Mr. #nathanael