This is a migrated thread and some comments may be shown as answers.

RadListView: Image files set in an array not showing

12 Answers 150 Views
ListView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Stan
Top achievements
Rank 1
Stan asked on 25 May 2017, 01:51 AM

Hello Forum,

I have an array with label descriptions. An array with image file names. An array with buttons with text. My labels display fine, my images are blank, my buttons show but with no text. No error messages. 

Any ideas on what I'm missing?

Thanks in advance. 

main-page.xml

<Page xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:lv="nativescript-telerik-ui/listview" loaded="pageLoaded">
    
    <ActionBar title="RadListView" />

    <lv:RadListView items="{{ myItems }}"> 
        <lv:RadListView.listViewLayout>
            <lv:ListViewGridLayout scrollDirection="Vertical" itemHeight="200" spanCount="3"/>
        </lv:RadListView.listViewLayout>
        <lv:RadListView.itemTemplate>
                <StackLayout>
                    <Label text="{{ $value }}" class="lable" textWrap="true" />
                    <Image src="{{ $parents['lv:RadListView'].myPics, $parents['lv:RadListView'].myPics }}" height="95" width="95" />
<Button text="{{ $parents['lv:RadListView'].myBtext, $parents['lv:RadListView'].myBtext }}" />
                </StackLayout>
        </lv:RadListView.itemTemplate>
    </lv:RadListView>

</Page>

main-page.js

var view = require("ui/core/view");
var image = require("ui/image");
var observable = require("data/observable");

var myDesc = [
    "Desc 1",
    "Desc 2", 
    "Desc 3",
    "Desc 4",
    "Desc 5",
    "Desc 6",
    "Desc 7",
    "Desc 8",
    "Desc 9"
];

var myImages = [
    "~/img/thb_AmFlagMap.png",
    "~/img/Thb_AmFlagMap.png",
    "~/img/Thb_AmFlagMap.png",
    "~/img/Thb_AmFlagMap.png",
    "~/img/Thb_AmFlagMap.png",
    "~/img/Thb_AmFlagMap.png",
    "~/img/Thb_AmFlagMap.png",
    "~/img/Thb_AmFlagMap.png",
    "~/img/Thb_AmFlagMap.png"
];

var myBtext = [
    "Tap 1",
    "Tap 2", 
    "Tap 3",
    "Tap 4",
    "Tap 5",
    "Tap 6",
    "Tap 7",
    "Tap 8",
    "Tap 9"
];

var viewModel = new observable.Observable();
    viewModel.set("myItems", myDesc);
    viewModel.set("myPics", myImages);
    viewModel.set("myBt", myBtext);

exports.pageLoaded = function(args) {
    var page = args.object;
    page.bindingContext = viewModel;
};

12 Answers, 1 is accepted

Sort by
0
Nikolay Tsonev
Telerik team
answered on 25 May 2017, 06:21 AM
Hello,
Thank you for your interest in UI for NativeScript.
I reviewed the case and found that the issue could be related to the way that the data is bind. Accessing the parent of the main list view for showing a value in the other component could lead to a problem and the value not to be shown properly.
My suggestion is to create a custom component with the needed properties and with its help to create the needed array, which to be bind to the RadListView source. For example:


XML
    <ActionBar title="RadListView" />
<GridLayout >
    <lv:RadListView items="{{ myItems }}" >
        <lv:RadListView.listViewLayout>
            <lv:ListViewLinearLayout scrollDirection="Vertical"/>
        </lv:RadListView.listViewLayout>
        <lv:RadListView.itemTemplate>
            <StackLayout orientation="vertical">
                <Label text="{{ title }}" class="lable" textWrap="true" />
                    <Image src="{{ imageurl }}" height="95" width="95" />
                    <Button text="{{ buttontitle }}" />
            </StackLayout>
        </lv:RadListView.itemTemplate>
    </lv:RadListView>
</GridLayout>
     
</Page>

TypeScript

import { EventData, Observable } from 'data/observable';
import {ObservableArray} from "data/observable-array"
import { Page } from 'ui/page';
import { HelloWorldModel } from './main-view-model';
 
 
class Item{
    constructor(public title, public imageurl, public buttontitle){}
}
 
 
export function pageLoaded(args: EventData) {
 
    let page = <Page>args.object;
     
 
    var viewModel = new Observable();
 
    var myArray=new ObservableArray();
    myArray.push(new Item("Desc 1", "~/img/test.png", "Tap 1"));
    myArray.push(new Item("Desc 2", "~/img/test.png", "Tap 2"));
    myArray.push(new Item("Desc 3", "~/img/test.png", "Tap 3"));
    viewModel.set("myItems", myArray);
    page.bindingContext = viewModel;
}

JavaScript
var observable_1 = require("data/observable");
var observable_array_1 = require("data/observable-array");
var Item = (function () {
    function Item(title, imageurl, buttontitle) {
        this.title = title;
        this.imageurl = imageurl;
        this.buttontitle = buttontitle;
    }
    return Item;
}());
function pageLoaded(args) {
    var page = args.object;
    var viewModel = new observable_1.Observable();
    var myArray = new observable_array_1.ObservableArray();
    myArray.push(new Item("Desc 1", "~/img/test.png", "Tap 1"));
    myArray.push(new Item("Desc 2", "~/img/test.png", "Tap 2"));
    myArray.push(new Item("Desc 3", "~/img/test.png", "Tap 3"));
    viewModel.set("myItems", myArray);
    page.bindingContext = viewModel;
}
exports.pageLoaded = pageLoaded;

I am also attaching the whole project.


For further help, you could review the sample project here.
If you still have a problem with the ListView, please provide some sample project, which could be debugged locally.


Regards,
nikolay.tsonev
Telerik by Progress
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Stan
Top achievements
Rank 1
answered on 26 May 2017, 12:14 AM
Thank you for your kind reply.

I'm sorry, I may not have been clear enough with my question.

I have three groups of elements, each group is in it's own array. Is there an easier way to do this and NOT have to parse each of my (3) arrays and assemble the three matching elements into a new array?

The sample project link ( https://github.com/telerik/nativescript-ui-samples/tree/release/sdk/app/listview/getting-started ) you sent looks like it may offer a solution for me, but unfortunately for me it's in TypeScript and I don't understand it enough to use it. Please, can you convert it into JavaScript? That would be a huge help, thank you in advance.
0
Accepted
Nikolay Tsonev
Telerik team
answered on 26 May 2017, 06:33 AM
Hello Stan,

I reviewed your case ones again and indeed you could access the other array in the XML  while using the $parents keyword, however, there is no way to get the index of the current element, which will allow you to load specific element from the other arrays.

This is known limitation for pure NativeScript project and we have already logged a feature request for this functionality here. For further info, you could keep track on it.

In the meantime as a temporary solution, you could use itemLoading event and with its help to get the Image and Button elements by id. Then you could setup src property for the Image and text for the Button. For example:

XML
<Page xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:lv="nativescript-telerik-ui/listview" loaded="pageLoaded">
     
    <ActionBar title="RadListView" />
 
    <lv:RadListView  items="{{ myItems }}" itemLoading="func">
        <lv:RadListView.listViewLayout>
            <lv:ListViewGridLayout scrollDirection="Vertical" itemHeight="200" spanCount="3"/>
        </lv:RadListView.listViewLayout>
        <lv:RadListView.itemTemplate>
                <StackLayout>
                 
                    <Label id="label" text="{{ $value }}" class="lable" textWrap="true" />
                    <Image id="pic" height="95" width="95" />
                    <Button id="bt" />
                </StackLayout>
        </lv:RadListView.itemTemplate>
    </lv:RadListView>
</Page>

JavaScript

var observable_1 = require("data/observable");
var myDesc = [
    "Desc 1",
    "Desc 2",
    "Desc 3",
    "Desc 4",
    "Desc 5",
    "Desc 6",
    "Desc 7",
    "Desc 8",
    "Desc 9"
];
var myImages = [
    "~/img/test.png",
    "~/img/test.png",
    "~/img/test.png",
    "~/img/test.png",
    "~/img/test.png",
    "~/img/test.png",
    "~/img/test.png",
    "~/img/test.png",
    "~/img/test.png"
];
var myBtext = [
    "Tap 1",
    "Tap 2",
    "Tap 3",
    "Tap 4",
    "Tap 5",
    "Tap 6",
    "Tap 7",
    "Tap 8",
    "Tap 9"
];
var Item = (function () {
    function Item(title, imageurl, buttontitle) {
        this.title = title;
        this.imageurl = imageurl;
        this.buttontitle = buttontitle;
    }
    return Item;
}());
function pageLoaded(args) {
    var page = args.object;
    var viewModel = new observable_1.Observable();
    viewModel.set("myItems", myDesc);
    viewModel.set("myPics", myImages);
    viewModel.set("myBt", myBtext);
    page.bindingContext = viewModel;
}
exports.pageLoaded = pageLoaded;
function func(args) {
    var layout = args.view;
    var image = layout.getViewById("pic");
    image.src = myImages[args.itemIndex];
    var button = layout.getViewById("bt");
    button.text = myBtext[args.itemIndex];
}
exports.func = func;


For further info, you could also review the attached sample project.


Regarding the other request. You could build the project on your side and all typescript files will be compiled to JavaScript. You could follow the steps:

1. git clone https://github.com/telerik/nativescript-ui-samples
2. cd --samples/
3. tns prepare <platform name>


 Hope this helps.
Regards,
nikolay.tsonev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Stan
Top achievements
Rank 1
answered on 26 May 2017, 09:15 PM

Thank you so much Nikolay, for your terrific work! That was the explanation and answer to my question I was looking for.

0
Stan
Top achievements
Rank 1
answered on 26 May 2017, 10:22 PM

Followup question: The function you have (below), I don't see it called or referenced anywhere else, where or how is that used? 

var Item = function () {
    function Item(title, imageurl, buttontitle) {
        this.title = title;
        this.imageurl = imageurl;
        this.buttontitle = buttontitle;
    }
    return Item;
};

0
Nikolay Tsonev
Telerik team
answered on 29 May 2017, 05:34 AM
Hello Stan,

The Item function was part of the first example, where has been demonstrated, how to load the data using a custom component with the needed properties, however, this part of the code is not needed at this time. I have just missed to remove it from the sample.

Regarding that, you could just ignore it and remove it from the project.

Let me know if I could assist you further.

Regards,
nikolay.tsonev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Stan
Top achievements
Rank 1
answered on 31 May 2017, 06:27 PM
Thank you.
0
Stan
Top achievements
Rank 1
answered on 08 Jun 2017, 12:05 AM

Follow up question #2: No changes in the main-page.xml file. I have a list of image files in my 'img' folder as in the previous code sample, I need to get that list of images and put it into myImage[]. I don't get any errors but no images show up either?

Thank you in advance...

main-page.js

var observable_1 = require("data/observable");
var fs = require("file-system");

var myDesc = [
    "Desc 1",
    "Desc 2", 
    "Desc 3",
    "Desc 4",
    "Desc 5",
    "Desc 6",
    "Desc 7",
    "Desc 8",
    "Desc 9"
];

var myImages = [];
var documents = fs.knownFolders.documents();
var myFolder = documents.getFolder("img");
myFolder.getEntities().then(function (entities) {
    entities.forEach(function (entity) {
        myImages = entity.name;
    });
    },
    function (error) {
        console.log("Error: " + error);
    });

var myBtext = [
    "Tap 1",
    "Tap 2",
    "Tap 3",
    "Tap 4",
    "Tap 5",
    "Tap 6",
    "Tap 7",
    "Tap 8",
    "Tap 9"
];

var viewModel = new observable_1.Observable();
    viewModel.set("myItems", myDesc);
    viewModel.set("myPics", myImages);
    viewModel.set("myBt", myBtext);

function pageLoaded(args) {
    var page = args.object;
    page.bindingContext = viewModel;
}
exports.pageLoaded = pageLoaded;

function func(args) {
    var layout = args.view;
    var image = layout.getViewById("pic");
    image.src = myImages[args.itemIndex];
    var button = layout.getViewById("bt");
    button.text = myBtext[args.itemIndex];
}
exports.func = func;

0
Nikolay Tsonev
Telerik team
answered on 08 Jun 2017, 06:40 AM
Hello Stan,
The issue in the sample code was related to the fact that knownFolders.documents() will return the application's 'documents' folder, where the images do not exist. What you are looking for is the `currecntApp()` method, which will give you the correct path to your application folder and you will be able to list all files from `img`.


Also, bear in mind that you should take the image sync which will allow loading the data in the ListView. For your help you could review the attached code sample:
XML
<Page xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:lv="nativescript-telerik-ui/listview" loaded="pageLoaded">
     
    <ActionBar title="RadListView" />
 
    <lv:RadListView  items="{{ myItems }}" itemLoading="func">
        <lv:RadListView.listViewLayout>
            <lv:ListViewGridLayout scrollDirection="Vertical" itemHeight="200" spanCount="3"/>
        </lv:RadListView.listViewLayout>
        <lv:RadListView.itemTemplate>
                <StackLayout>
                 
                    <Label id="label" text="{{ $value }}" class="lable" textWrap="true" />
                    <Image id="pic" height="95" width="95" />
                    <Button id="bt" />
                </StackLayout>
        </lv:RadListView.itemTemplate>
    </lv:RadListView>
</Page>

TyeScript 
import { EventData, Observable } from 'data/observable';
import {ObservableArray} from "data/observable-array"
import { Page } from 'ui/page';
import { HelloWorldModel } from './main-view-model';
import {ListView, ItemEventData} from "tns-core-modules/ui/list-view";
import {StackLayout} from "tns-core-modules/ui/layouts/stack-layout";
import {Image} from "tns-core-modules/ui/image";
import {Button} from "tns-core-modules/ui/button";
import {knownFolders, Folder, FileSystemEntity} from "file-system";
 
 
var myDesc = [
    "Desc 1",
    "Desc 2",
    "Desc 3",
    "Desc 4",
    "Desc 5"
];
 
var myImages=[];
 
var myBtext = [
    "Tap 1",
    "Tap 2",
    "Tap 3",
    "Tap 4",
    "Tap 5"
];
 
class Item{
    constructor(public title, public imageurl, public buttontitle){}
}
 
 
export function pageLoaded(args: EventData) {
readFiles();
    let page = <Page>args.object;
     
console.log("start data loading")
console.dir(myImages);
    var viewModel = new Observable();
 
 
    viewModel.set("myItems", myDesc);
    viewModel.set("myPics", myImages);
    viewModel.set("myBt", myBtext);
    page.bindingContext = viewModel;
}
export function func(args){
    var layout:StackLayout=<StackLayout>args.view;
    var image:Image=<Image>layout.getViewById("pic");
    image.src=myImages[args.itemIndex];
    var button:Button=<Button>layout.getViewById("bt");
    button.text=myBtext[args.itemIndex];
}
 
 
function readFiles(){
    var documents = knownFolders.currentApp();
 
    var myFolder:Folder = documents.getFolder("img");
    
    var array= myFolder.getEntitiesSync();
    console.log("array 1");
    console.dir(array);
    (<any>array).forEach(element => {
        myImages.push(element._path);
    });
    console.log("get image end")
     
}

JavaScript
var observable_1 = require("data/observable");
var file_system_1 = require("file-system");
var myDesc = [
    "Desc 1",
    "Desc 2",
    "Desc 3",
    "Desc 4",
    "Desc 5"
];
var myImages = [];
var myBtext = [
    "Tap 1",
    "Tap 2",
    "Tap 3",
    "Tap 4",
    "Tap 5"
];
var Item = (function () {
    function Item(title, imageurl, buttontitle) {
        this.title = title;
        this.imageurl = imageurl;
        this.buttontitle = buttontitle;
    }
    return Item;
}());
function pageLoaded(args) {
    readFiles();
    var page = args.object;
    console.log("start data loading");
    console.dir(myImages);
    var viewModel = new observable_1.Observable();
    viewModel.set("myItems", myDesc);
    viewModel.set("myPics", myImages);
    viewModel.set("myBt", myBtext);
    page.bindingContext = viewModel;
}
exports.pageLoaded = pageLoaded;
function func(args) {
    var layout = args.view;
    var image = layout.getViewById("pic");
    image.src = myImages[args.itemIndex];
    var button = layout.getViewById("bt");
    button.text = myBtext[args.itemIndex];
}
exports.func = func;
function readFiles() {
    var documents = file_system_1.knownFolders.currentApp();
    var myFolder = documents.getFolder("img");
    var array = myFolder.getEntitiesSync();
    console.log("array 1");
    console.dir(array);
    array.forEach(function (element) {
        myImages.push(element._path);
    });
    console.log("get image end");
}
Hope this helps
Regards,
nikolay.tsonev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Stan
Top achievements
Rank 1
answered on 08 Jun 2017, 11:52 PM
Thank you. That was a big help.
0
Stan
Top achievements
Rank 1
answered on 16 Jun 2017, 02:34 AM

Follow up question #3: 'ItemTap event' I got from https://docs.nativescript.org/cookbook/ui/list-view#itemtap-event.
Thank you in advance...

No changes in my main-page.xml file. 
I get an error "unexpected token" when I do:
listView.on(listViewModule.ListView.itemTapEvent, function (args: listViewModule.ItemEventData) {
    var tappedItemIndex = args.index;
    var tappedItemView = args.view;
    // Do someting
});

I get an error "listview is not a constructor" when I do:
listView.on(listViewModule.ListView.itemTapEvent, function (args) {
    var tappedItemIndex = args.index;
    var tappedItemView = args.view;
    // Do someting
});

main-page.js

var observable_1 = require("data/observable");
var file_system_1 = require("file-system");
var listViewModule = require("nativescript-telerik-ui/listview");
var myDesc = [
    "Desc 1",
    "Desc 2",
    "Desc 3",
    "Desc 4",
    "Desc 5"
];
var myImages = [];
var myBtext = [
    "Tap 1",
    "Tap 2",
    "Tap 3",
    "Tap 4",
    "Tap 5"
];
function pageLoaded(args) {
    readFiles();
    var page = args.object;
    console.log("start data loading");
    console.dir(myImages);
    var viewModel = new observable_1.Observable();
    viewModel.set("myItems", myDesc);
    viewModel.set("myPics", myImages);
    viewModel.set("myBt", myBtext);
    page.bindingContext = viewModel;
}
exports.pageLoaded = pageLoaded;
function func(args) {
    var layout = args.view;
    var image = layout.getViewById("pic");
    image.src = myImages[args.itemIndex];
    var button = layout.getViewById("bt");
    button.text = myBtext[args.itemIndex];
}
var listView_1 = new listViewModule();
listView_1.on(listViewModule.ListView.itemTapEvent, function(args) {
    var tappedItemIndex = args.index;
    var tappedItemView = args.view;
    console.log(tappedItemIndex)
});
exports.func = func;
function readFiles() {
    var documents = file_system_1.knownFolders.currentApp();
    var myFolder = documents.getFolder("img");
    var array = myFolder.getEntitiesSync();
    console.log("array 1");
    console.dir(array);
    array.forEach(function (element) {
        myImages.push(element._path);
    });
    console.log("get image end");
}

0
Nikolay Tsonev
Telerik team
answered on 16 Jun 2017, 06:20 AM
Hi Stan,

The issue in the code is related to the way that you are attaching to the itemTapEvent. 
One way to handle this event is to set up the event name and the name of the callback method in the XML and to define this callback in the code behind. For example:
main-page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:lv="nativescript-telerik-ui/listview" loaded="pageLoaded">
     
    <ActionBar title="RadListView" />
 
    <lv:RadListView itemTap="onItemTap"  items="{{ myItems }}" itemLoading="func">
        <lv:RadListView.listViewLayout>
            <lv:ListViewGridLayout scrollDirection="Vertical" itemHeight="200" spanCount="3"/>
        </lv:RadListView.listViewLayout>
        <lv:RadListView.itemTemplate>
                <StackLayout>
                 
                    <Label id="label" text="{{ $value }}" class="lable" textWrap="true" />
                    <Image id="pic" height="95" width="95" />
                    <Button id="bt" />
                </StackLayout>
        </lv:RadListView.itemTemplate>
    </lv:RadListView>
</Page>

main-page.ts
export function onItemTap(args){
    console.log("selected item index "+args.itemIndex);
}
main-page.js
export function onItemTap(args){
    console.log("selected item index "+args.itemIndex);
}
Another option is to use the `on` method as you did, however, this should be done on RadListView loaded event. You could follow the code:

main-page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:lv="nativescript-telerik-ui/listview" loaded="pageLoaded">
     
    <ActionBar title="RadListView" />
 
    <lv:RadListView loaded="lvloaded"   items="{{ myItems }}" itemLoading="func">
        <lv:RadListView.listViewLayout>
            <lv:ListViewGridLayout scrollDirection="Vertical" itemHeight="200" spanCount="3"/>
        </lv:RadListView.listViewLayout>
        <lv:RadListView.itemTemplate>
                <StackLayout>
                 
                    <Label id="label" text="{{ $value }}" class="lable" textWrap="true" />
                    <Image id="pic" height="95" width="95" />
                    <Button id="bt" />
                </StackLayout>
        </lv:RadListView.itemTemplate>
    </lv:RadListView>
</Page>

main-page.ts
import { EventData, Observable } from 'data/observable';
import {ObservableArray} from "data/observable-array"
import { Page } from 'ui/page';
import { HelloWorldModel } from './main-view-model';
import {StackLayout} from "tns-core-modules/ui/layouts/stack-layout";
import {Image} from "tns-core-modules/ui/image";
import {Button} from "tns-core-modules/ui/button";
import {knownFolders, Folder, FileSystemEntity} from "file-system";
import {RadListView, ListViewEventData} from "nativescript-telerik-ui/listview"
 
 
....................................................
export function lvloaded(args){
    var listview:RadListView = <RadListView>args.object;
    listview.on(RadListView.itemTapEvent, function(args:ListViewEventData){
        console.log("selected item index "+args.itemIndex);
    })
}

main-page.js
var observable_1 = require("data/observable");
var file_system_1 = require("file-system");
var listview_1 = require("nativescript-telerik-ui/listview");
.............................................
 
function lvloaded(args) {
    var listview = args.object;
    listview.on(listview_1.RadListView.itemTapEvent, function (args) {
        console.log("selected item index " + args.itemIndex);
    });
}
exports.lvloaded = lvloaded;


Something that I notice is that you are using the documentation for the pure NativeScript ListView, instead of the this for RadListView, which is provided by nativescript-telerik-ui plugin and which you use in your project.
The right resources could be found in this documentation here and for further help, you could use this sample project.


It would also help if you could open a new ticket for every individual problem, which you have. This will help to separate the issues and also it will be easier for the others to find the solution while reading the forum
Regards,
nikolay.tsonev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
Tags
ListView
Asked by
Stan
Top achievements
Rank 1
Answers by
Nikolay Tsonev
Telerik team
Stan
Top achievements
Rank 1
Share this question
or