nativescript-vue
nativescript-vue copied to clipboard
Expose `itemTemplateSelector ` for the `ListView` ns-core Layout
What problem does this feature solve?
It will have better performance when it comes to loading huge lists, as the item selector will fetch and feed the views that only map the selector criteria.
What does the proposed API look like?
<ListView :items="<collection-containing-objects>" :itemTemplateSelector="selector">
<v-template name="banner">
....
</v-template>
<v-template name="content">
...
</v-template>
</ListView>
selector(item) {
return <expression-based-on-item-content> ? 'banner' : 'content';
}
This should already work iirc
I have created this small demo clean app to try out on it. https://github.com/adel12790/ns-vue-list-demo
Outputs an error and crashes on both iOS and Android.
TypeError: Cannot read property 'scopedFn' of undefined
I have tried to search for this error, but I couldn't find a reasonable answer.
I have checked the @ns/core module packages @nativescript/core/ui/list-view
and I guess we need to specify an itemTemplates
wrapper to be able to use the selector.
But I couldn't manage to do it.
Same here I'm using NativeScript 7.3.0 but I can't seem to get it to work. Documentation seems lacking with regards to this subject. I've based my code on examples using vanilla NativeScript and NativeScript Angular but my code resulted in:
TypeError: Cannot read property 'scopedFn' of undefined
I've been trying to find an example of how it should be used with NativeScript Vue but no luck so far.
I've investigated a bit and to me there seems to be a bug in the mounted
lifecycle hook:
https://github.com/nativescript-vue/nativescript-vue/blob/8341c128860e7874b990269ffd063f802ecc9ae8/platform/nativescript/runtime/components/v-template.js#L17-L29
If I'm understanding the code correctly here in line 27 it's always the default
slot that's being passed. The error TypeError: Cannot read property 'scopedFn' of undefined
only occurs when there isn't a template with the name default
, just like @adel12790's example.
This will break
<template>
<GridLayout class="list-wrapper">
<ListView class="list"
:items="dataList"
:itemTemplateSelector="selector"
>
<v-template name="fruit">
<Label :text="`Sweat ${item.name}`" />
</v-template>
<v-template name="veggies">
<Label :text="item.name" />
</v-template>
</ListView>
</GridLayout>
</template>
This won't break, but only default template will be used
<template>
<GridLayout class="list-wrapper">
<ListView class="list"
:items="dataList"
:itemTemplateSelector="selector"
>
<!-- Set template to "default" or else don't set a name,
which internally will set template name to "default" -->
<v-template name="default">
<Label :text="`Sweat ${item.name}`" />
</v-template>
<v-template name="veggies">
<Label :text="item.name" />
</v-template>
</ListView>
</GridLayout>
</template>
So what if we want to have templates branching within the list, so we might add the default for fallbacks, but still need the other ones to show based on the item selector.
@adel12790 I've managed to find out how to make it work. It's listed in the documentation and I think last time I missed it.
So you have to use the if
prop - Reference.
Using the same example as above you can have something like so:
<template>
<GridLayout class="list-wrapper">
<ListView class="list" for="item in dataList">
<v-template if="item.type === 'fruit'">
<Label :text="`Sweat ${item.name}`" />
</v-template>
<v-template if="item.type === 'veggies'">
<Label :text="item.name" />
</v-template>
</ListView>
</GridLayout>
</template>
According to the documentation in the if
prop you can use the following variables:
