Custom component on list gradually stops receiving loaded event


#1

Here is the problem:

  • Build a list of items containing an id.
  • For each item in the list, print its item id as Label directly from le list (xml) and through a custom component (which is triggered by “loaded” event) that prints the item id as well.
  • After a number of items where label and component values are the same, they start to differ.
  • Moreover printing item id on console, from its clear that the difference starts where the component does not receive the loaded event.

Please check the code an result below.

The page

<Page
    class="page"
    loaded="onLoaded"  
    navigatingTo="onNavigatingTo"  
    xmlns:tag="components/tag/get"
    xmlns="http://schemas.nativescript.org/tns.xsd">

    <StackLayout orientation="vertical" class="border-divider-top">
        <ListView items="{{ items }}">
            <ListView.itemTemplate>
                <StackLayout orientation="vertical" class="border-divider-top">
                    <Label    text="{{'From Label        ' + itemId }}"></Label>
                    <tag:get tagId="{{'From Comp.      ' + itemId + ' *' }}"/>
                </StackLayout>
            </ListView.itemTemplate>
        </ListView>
    </StackLayout>    
</Page>

The view model

const observableModule = require("data/observable");
function BrowseViewModel() {
    const viewModel = observableModule.fromObject({
        /* Add your view model properties here */
        items: [
            { itemId: "1" },
            { itemId: "2" },
            { itemId: "3" },
            { itemId: "4" },
            { itemId: "5" },
            { itemId: "6" },
            { itemId: "7" },
            { itemId: "8" },
            { itemId: "9" },
            { itemId: "10" },
            { itemId: "11" },
            { itemId: "12" },
            { itemId: "13" },
            { itemId: "14" },
            { itemId: "15" },
            { itemId: "16" },
            { itemId: "17" },
            { itemId: "18" },
            { itemId: "19" },
            { itemId: "20" }
        ]
    });
    return viewModel;
}
module.exports = BrowseViewModel;

Custom component (.ts)

import { Label } from "tns-core-modules/ui/label";
import { View } from "tns-core-modules/ui/core/view";
class TagGet extends View {  
    tagId: string;
}

// this will get called when our <GridLayout> is loaded
export function onLoad(args: any) {  
    // args.object is a reference to the view, and every View instance has a "loaded" event
    let thisView: TagGet = <TagGet>args.object;
    console.log("$$$$$ " + thisView.tagId);    
    // only change the label's text if we were given some custom headingText
    let tagId = <Label>thisView.getViewById('tag-id');
    tagId.text = thisView.tagId;
}

Custom component (.xml)

<StackLayout orientation="horizontal" loaded="onLoad">
    <Label id="tag-id" text="?" />
</StackLayout> 

Result on app
From index 13 items id print start to differ.

While on console…

Note as printings differs where event is missing, i.e for 13 and 15 to 20.

CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      1 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      2 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      3 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      4 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      5 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      6 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      7 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      8 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      9 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      10 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      11 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      12 *
CONSOLE LOG file:///app/components/tag/get/get.js:27:16: $$$$$ From Comp.      14 *

#2

ListView recycles the templates, the elements scrolled above may be reused for elements below - thats intended to improve performance, that’s by design in both iOS and Android.


#3

Thanks for your reply, ok I’ve read more info about recycle.

So, how it is possible to use a custom component from within a list item in order that its value is updated after template recycling?

I’m a beginner on {NS} so thanks a lot for any help and references.


#4

You don’t have to bother about recycle it’s done by system. But I’m wondering why you depend on loaded event. If you let us know may be we can suggest some different approach.


#5

The loaded event triggers the custom component (CC) to set values (received as parameters from where it’s placed) in its template (see CC .ts and .xml code).
I found this procedure in many examples.

Now, it seems clear that when a view containing a CC is recycled the loaded event to CC is not fired anymore, so it is not updated, and this sounds strange to me.

Please do you have any suggestion/workaround?
Thanks!

PS Anyway I need to make a sort of facebook likes counters that are everywhere and in multiple (and several) instances on the same page, that’s why I need CC.


#6

Implement a custom property (getter and setter) for the custom component, in the setter funtion you will get updates on every change.


#7

Exactly! Just done and (after many trials this afternoon) it works!!
By the way… as far as I know about NS… I found very strange the fact that a custom component within ListView item, once recycled, does not receive the loaded event anymore. Thats forces to write CC in full code instead of code+xml…

Thanx for your help!


#8

May be that’s a limitation of NativeScript Core, which is why you already have support for frameworks like Angular / Vue that on-boards a lot of built in options to manage your template.

In my perspective, it’s not worth or a overhead to simply reimplement all those templating features in NativeScript Core. I would recommend adopt those frameworks as your project needs,

  • NativeScript Core - Simple apps
  • Vue - Complicated and medium scale apps
  • Angular - Enterprise & extremely large scale apps

#9

I’m evaluating porting on NS a fairly complex Cordova app, based on Handlebars and JQM.
NS seems promising ath the beginning but has some pitfall and is not much documented. I spent 3 days to get find out a solution for the problem above… I will have a look look to Vue as well… Thanx!


#10

I’m sorry to hear that, but I started with {N} when it was 2.x and I believe the documentation was good then and much better now. May be if you let me know what exactly you couldn’t find, I can point you.

Vue / Angular are just frameworks that helps in reusing your existing knowledge or features provided by framework.