Skip to content
New issue

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

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

Already on GitHub? # to your account

Emitted events are blocked in VueTemplate class composition #28

Open
jeffery9876 opened this issue May 21, 2021 · 1 comment
Open

Emitted events are blocked in VueTemplate class composition #28

jeffery9876 opened this issue May 21, 2021 · 1 comment

Comments

@jeffery9876
Copy link

jeffery9876 commented May 21, 2021

Thanks for the great project. I was following the notebook here for creating Vue components using the new syntax vue.VueTemplate.class_component_serialization. But no event can be pass from sub-component to main-component


This example works, and the parent can received the event my-event from child component

import ipyvue as vue
import traitlets

class Parent(vue.VueTemplate):
    
    someProp = traitlets.Unicode('hello').tag(sync=True)
    
    components = traitlets.Dict({'Child': '''
        <template>
            <div>
                Prop from parent: 
                <h3> {{ childProp}} </h3>
                <button @click="$emit('my-event', 'new value')">change</button>
            </div>
        </template>
        <script>
            module.exports = {
                props: ['childProp'],
            }
        </script>
    '''}).tag(sync=True)

    template = traitlets.Unicode('''
        <template>
            <div>
                <div>parent</div>
                <Child :child-prop="someProp" @my-event='test'></Child>
                <h3>Parent: {{ someProp }} </h3>
            </div>
        </template>
    ''').tag(sync=True)

    
    def vue_test(self, data):
        print('received from child')
        self.someProp = 'changed'
    
parent = Parent()
parent

If I move the child component into a VueTemplate class, The GUI is rendered correctly, however the event my-event is blocked. No event can be pass from Child to Parent

The parent did not receive the event.

class Child(vue.VueTemplate):
    childProp = traitlets.Unicode('childProp').tag(sync=True)
    template = traitlets.Unicode('''
        <template>
            <div>
                Prop from parent: 
                <h3> {{ childProp }} </h3>
                <button @click="$emit('my-event', 'new value')">change</button>
            </div>
        </template>

    ''').tag(sync=True)
    

class Parent2(vue.VueTemplate):
    someProp = traitlets.Unicode('hello').tag(sync=True)

    template = traitlets.Unicode('''
        <template>
            <div>
                <Child :child-prop="someProp" @my-event="test"></Child>
                <h3>Parent: {{ someProp }} </h3>
            </div>
        </template>
    ''').tag(sync=True)
    
    components = traitlets.Dict({
        'Child': Child
    }).tag(sync=True, **vue.VueTemplate.class_component_serialization)
    
    def vue_test(self, data):
        print('can not receive from child')
        self.someProp = 'not changed'

        
parent = Parent2()
parent

Is this due to the different implementation on event handling between the VueModel and VueTemplate ?

@etienne-monier
Copy link

Hi, I'd like to know if someone investigated this issue.
As I define pythonic callback, I need to use the second above example.
To get around this problem, I need to define a parent attribute for child class.

import ipyvue as vue
import ipywidgets
import traitlets

class Child(vue.VueTemplate):
    childProp = traitlets.Unicode('childProp').tag(sync=True)
    template = traitlets.Unicode('''
        <template>
            <div>
                Prop from parent: 
                <h3> {{ childProp }} </h3>
                <button @click="at_click('new value')">change</button>
            </div>
        </template>

    ''').tag(sync=True)

    def __init__(self, parent=None, *args, **kwargs):
        vue.VueTemplate.__init__(self, *args, **kwargs)
        self.parent = parent

    def vue_at_click(self, value):
        """Callback called when clicking on the button"""
        if parent is not None:
            self.parent.test()
    

class Parent2(vue.VueTemplate):
    someProp = traitlets.Unicode('hello').tag(sync=True)

    child = traitlets.Any().tag(
        sync=True, **ipywidgets.widget_serialization
    )

    template = traitlets.Unicode('''
        <template>
            <div>
                <jupyter-widget :widget="child" />
                <h3>Parent: {{ someProp }} </h3>
            </div>
        </template>
    ''').tag(sync=True)
    
    def __init__(self, parent=None, *args, **kwargs):
        vue.VueTemplate.__init__(self, *args, **kwargs)
        self.child = Child(parent=self, childProp="hack")
    
    def test(self, data):
        print('can not receive from child')
        self.someProp = 'not changed'

        
parent = Parent2()
parent

PS: I instead usually use ipyvuetify

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

No branches or pull requests

2 participants