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

clarification on new Event structure #8

Open
havok2063 opened this issue Feb 10, 2020 · 4 comments
Open

clarification on new Event structure #8

havok2063 opened this issue Feb 10, 2020 · 4 comments

Comments

@havok2063
Copy link

I had some questions on the new Event demos from the recent PR #3. 1. Is it strictly necessary to create a subclass of a Vuetify object just to add a simple event accessible to front-end components? My case involves a single v.Row component containing three bqplot components I need updated on a drop-down select change. Inside my notebook, I subclassed v.Row to include my on-change event function.

class UpdateRow(v.Row):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.on_event('change', update_data)    

UpdateRow(_metadata={'mount_id': 'protospec'}, dense=True, row=True, wrap=True, align_center=True, children=[

    # load the histogram and slider content
    v.Col(xs12=True, lg6=True, xl4=True, children=[
        img
    ]),

    # load the line plot content
    v.Col(xs12=True, xl4=True, children=[
        spec2d
    ]),
    # load the line plot content
    v.Col(xs12=True, xl4=True, children=[
        fig
    ]),       
])

with my update_data function defined as

def update_data(widget, event, data):
    # get new data from selected target
    selected_src = int(data)
    hdu1d, hdu, cut = prep_data(selected_src)

    # update spec1d data
    wave, flux = get_xy(hdu1d[1].data)
    plot.y = flux
    plot.x = wave

    # update spec2d data
    i = PercentileInterval(95)
    heat.color = i(hdu[1].data)

    # update image cutout data
    image.color = cut[0].data
    img.title = 'Src {0}'.format(selected_src)

However if I need to attach my event to multiple components, I'd have to subclass every single one. Is it possible to expand event function definitions so they could be linked to one or multiple components, without subclassing every component you need to attach to it? Something like

v.Row(_metadata={'mount_id': 'protospec'} .... )

def update_data(widget, event, data, mount_to=['protospec:change']):
    ...
  1. Is there an advantage to putting the requestWidget call inside Vue's created block? My front-end looks like
    <v-row>
        <v-col class='col-md-2'>
            <v-select :items="items" dense=True label="Outside Component Select" @change='update_data'></v-select>
        </v-col>
    </v-row>

with the update_data method defined as

        methods: {
            update_data(event) {
                requestWidget({
                    voilaUrl: 'http://localhost:8000',
                    notebook: 'spec_viewers.ipynb',
                    mountId: 'protospec',
                }).then(sevent => {
                    sevent.send({event: 'change', data: event})
                });
            }
        }

Is this reasonable or does this cause unnecessary network calls?

@mariobuikhuizen
Copy link
Owner

  1. You could do this:
def update_data(widget, event, data):
    ...

row1 = v.Row(.... )
row1.on_event('change', update_data)
...
rowN = v.Row(...)
rowN.on_event('change', update_data)
  1. In the example we wanted the widget-models to be available as early as possible, so the create lifecycle method was the first choice. We kept a reference to it for further interactions. Calling requestWidget does not cause any network calls, it just returns a promise to a widget-model that will be loaded anyway. So your solution is just as efficient and, when using the model only in one place, more concise. In hindsight, we could've used this in the example, we just didn't come up with the idea.

I want to point out that since you already use vue template syntax in the front-end, you may want to use this in the notebook/python too. This is not very well document yet, but I think you can get a long way with the examples: https://github.com/mariobuikhuizen/ipyvuetify/blob/master/examples/Examples%20template.ipynb. This is also being used in https://github.com/spacetelescope/jdaviz and https://github.com/glue-viz/glue-jupyter. The events work differently in this mode, so if you decide to use it we have to think about question 1 again.

@havok2063
Copy link
Author

Thanks for the clarification! This is helpful. Yeah your example makes sense if you need to access the model multiple times from multiple places. And good to know there's no downside to where you place the requestWidget in the Vue lifecycle.

I think you're right and we'll end up using the template syntax. Since our plan is to ultimately utilize jdaviz, I think we'll end up building a custom template that plugs into jdaviz. Our team is also planning on building out separate Vue templates and components for other services, that will exist independently of Voila and notebooks, but where we still want the option of plugging in Voila served components. So I'm exploring mechanisms for mixing front-end templates with Voila-embedded templates and controlling widgets from alternately-defined front-end components.

@maartenbreddels
Copy link
Collaborator

Our team is also planning on building out separate Vue templates and components for other services, that will exist independently of Voila and notebooks, but where we still want the option of plugging in Voila served components.

Good to hear, and looking forward to feedback on how that works out.

Slightly related,

In vaex, i started to put the templates in separate files, e.g.:
https://github.com/vaexio/vaex/blob/54d5d30e28360cbc0d35de9cba0c09c3c6ab016e/packages/vaex-jupyter/vaex/jupyter/widgets.py#L323
Which uses:
https://github.com/vaexio/vaex/blob/54d5d30e28360cbc0d35de9cba0c09c3c6ab016e/packages/vaex-jupyter/vaex/jupyter/columnlist.vue

This makes is possible to use a .vue file in both a Python widget and vue (although not everything is supported in the widget case). And it also gives you syntax highlighting.

@havok2063
Copy link
Author

Thanks Maarten! That's really interesting and a good example to pull from of how these things can sync up! This is helpful!

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

3 participants