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

v-select does not work as expected when used as Child Component with VuetifyTemplate #149

Open
gioxc88 opened this issue May 21, 2021 · 2 comments

Comments

@gioxc88
Copy link

gioxc88 commented May 21, 2021

I am not sure the problem is related only to v-select but it might be more general.
Below an example:

  1. I define a very simple Select component (WORKS)
import ipywidgets as widgets
import ipyvue as vue
from traitlets import Dict, Unicode, List
import ipyvuetify as v


select_template= '''
    <template>
    <v-row align="center">
        <v-col cols="4">
            <v-select :items="items" label="Test"></v-select>
        </v-col>
    </v-row>
    </template>
    <script>
    module.exports = {
        props: ["items"]
    }
    </script>
'''

class Select(v.VuetifyTemplate):
    items = List([]).tag(sync=True)
    template = Unicode(select_template).tag(sync=True)

Select(items=['a', 'b', 'c'])

image

  1. I put this component in a Main component using the Select class directly (DOESN'T WORK as expected)
    Clicking on the arrow to show the menu items is not working.
class Main(v.VuetifyTemplate):
    items = List([]).tag(sync=True)
    template = Unicode('''
        <template>
            <v-card>
                <v-card-title>Showing SubComponents</v-card-title>
                <my-select :items="items"/>
            </v-card>
        </template>
    ''').tag(sync=True)
    
    components=Dict({
        'my-select': Select,
    }).tag(sync=True, **v.VuetifyTemplate.class_component_serialization)

Main(items=['a', 'b', 'c'])

image

  1. I do the same thing but I specify the component as a string using template instead of using the Select class (WORKS)
class Main(v.VuetifyTemplate):
    items = List([]).tag(sync=True)
    template = Unicode('''
        <template>
            <v-card>
                <v-card-title>Showing SubComponents</v-card-title>
                <my-select :items="items"/>
            </v-card>
        </template>
    ''').tag(sync=True)
    
    components=Dict({
        'my-select': select_template,
    }).tag(sync=True, **v.VuetifyTemplate.class_component_serialization)

Main(items=['a', 'b', 'c'])

image

  1. Finally if I use the class as a component instead of the template string I am also experiencing the same problem of this issue on ipyvue about the events emitted by the Child not been sent to the Parent

Any help on this would be appreciated.
Many thanks
Gio

@gioxc88 gioxc88 changed the title v-select does not work as as Child Component in when using VuetifyTemplate v-select does not work as expected when used as Child Component with VuetifyTemplate May 21, 2021
@etienne-monier
Copy link

I produced the same error ...
Help !

@etienne-monier
Copy link

I'll be more explicit.

I defined a template vue based ont the following file:

<v-select v-model="selected" :items="items" :label="label" multiple>
    <template v-slot:prepend-item>
        <v-list-item ripple @click="toggle">
            <v-list-item-action>
                <v-icon :color="selected.length > 0 ? 'indigo darken-4' : ''">
                    {{ icon }}
                </v-icon>
            </v-list-item-action>
            <v-list-item-content>
                <v-list-item-title>
                    Select All
                </v-list-item-title>
            </v-list-item-content>
        </v-list-item>
        <v-divider class="mt-2"></v-divider>
    </template>
</v-select>
<script>
    export default {

        computed: {

            allSelected() {
                return this.selected.length === this.items.length
            },
            someSelected() {
                return this.selected.length > 0 && !this.allSelected
            },
            icon() {
                if (this.allSelected) return 'mdi-close-box'
                if (this.someSelected) return 'mdi-minus-box'
                return 'mdi-checkbox-blank-outline'
            },
        },

        methods: {
            toggle() {
                this.$nextTick(() => {
                    if (this.allSelected) {
                        this.selected = []
                    } else {
                        this.selected = this.items.slice()
                    }
                })
            },
        },
    }
    <script>
    module.exports = {
        props: ["items", "selected", "label"]
    }
    </script>
</script>

I created the following template class.

class SelectIntVue(v.VuetifyTemplate):
    template_file = str(VUE_ROOT / "select.vue")
    items = traitlets.List(traitlets.Int(), default_value=None).tag(sync=True)
    selected = traitlets.List(traitlets.Int(), default_value=None).tag(
        sync=True
    )
    label = traitlets.Unicode(default_value="").tag(sync=True)

I'd like to incorporate it in a basic form, but I got inspired from the @gioxc88 method. In fact, incorporating a widget trait is not perfect as I should need to create the slider before incorporating it to the form. That's correct for a simple form, but that's not for a complex application.

I then tried the 3rd point solution from @gioxc88 and produced something like this

select = """
<template>
<v-select v-model="selected" :items="items" :label="label" multiple>
    <template v-slot:prepend-item>
        <v-list-item ripple @click="toggle">
            <v-list-item-action>
                <v-icon :color="selected.length > 0 ? 'indigo darken-4' : ''">
                    {{ icon }}
                </v-icon>
            </v-list-item-action>
            <v-list-item-content>
                <v-list-item-title>
                    Select All
                </v-list-item-title>
            </v-list-item-content>
        </v-list-item>
        <v-divider class="mt-2"></v-divider>
    </template>
</v-select>
</template>
<script>
    module.exports = {
        props: ["items", "selected", "label"],
    },
    export default {
        props: ["items", "selected", "label"],
        computed: {

            allSelected() {
                return this.selected.length === this.items.length
            },
            someSelected() {
                return this.selected.length > 0 && !this.allSelected
            },
            icon() {
                if (this.allSelected) return 'mdi-close-box'
                if (this.someSelected) return 'mdi-minus-box'
                return 'mdi-checkbox-blank-outline'
            },
        },

        methods: {
            toggle() {
                this.$nextTick(() => {
                    if (this.allSelected) {
                        this.selected = []
                    } else {
                        this.selected = this.items.slice()
                    }
                })
            },
        },
    }
</script>
"""

but when I use it in this example

class CreateForm(v.VuetifyTemplate):
    
    id_items = traitlets.List(traitlets.Int(), default_value=None).tag(sync=True)
    category_items = traitlets.List(traitlets.Unicode(), default_value=None).tag(sync=True)
    selectedCategory = traitlets.Unicode("").tag(sync=True)
    
    components = traitlets.Dict({
        'my-select': select,
    }).tag(sync=True, **v.VuetifyTemplate.class_component_serialization)

    @traitlets.default('template')
    def _template(self):
        return '''
<v-card>
    <v-card-title>
        <span class="text-h5">A test</span>
    </v-card-title>
    <v-card-text>
        <v-container fluid>
            <v-row>
                <v-col cols="12" sm="6">
                    <my-select :items="id_items" label="Sat. id" />
                </v-col>
                <v-col cols="12" sm="6">
                    <v-select v-model="selectedCategory" :items="category_items" label="Category" required></v-select>
                </v-col>
            </v-row>
        </v-container>
    </v-card-text>
    <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn color="blue darken-1" text @click="close_form">
            Close
        </v-btn>
        <v-btn color="blue darken-1" text @click="send_form">
            Create
        </v-btn>
    </v-card-actions>
</v-card>
<script>
    export default {
        methods: {
            close_form() {
                this.$emit('closeForm')
            },
            send_form() {
                this.$emit('closeForm', selectedCategory)
            }
        }
    }
</script>
'''

id_items=[0, 1, 2, 3, 4, 5]
category_list = ['a', 'b']
form = CreateForm(id_items=id_items, category_items=category_list)
form

This does not display the slider.

bug

(by the way, is there a log or a debug mode specific to vuetify? This would help to know why something does not display)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants