Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose itemTemplateSelector for the ListView ns-core Layout #957

Open
adel12790 opened this issue Mar 29, 2022 · 6 comments
Open

Expose itemTemplateSelector for the ListView ns-core Layout #957

adel12790 opened this issue Mar 29, 2022 · 6 comments
Labels
priority:normal V2 Issues related to V2

Comments

@adel12790
Copy link

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';
}
@rigor789
Copy link
Member

This should already work iirc

@adel12790
Copy link
Author

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.

@dangrima90
Copy link

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.

@dangrima90
Copy link

I've investigated a bit and to me there seems to be a bug in the mounted lifecycle hook:

mounted() {
if (!this.$scopedSlots.default) {
return
}
this.$templates = this.$el.parentNode.$templates = this.$parent.$templates =
this.$parent.$templates || new TemplateBag()
this.$templates.registerTemplate(
this.$props.name || (this.$props.if ? `v-template-${tid++}` : 'default'),
this.$props.if,
this.$scopedSlots.default
)
},

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>

@adel12790
Copy link
Author

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.

@dangrima90
Copy link

dangrima90 commented Jun 28, 2022

@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:

image

@rigor789 rigor789 added the V2 Issues related to V2 label Dec 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority:normal V2 Issues related to V2
Development

No branches or pull requests

4 participants