From d18f66af19527bfa0eb47fcdd1ab50772d00fbe5 Mon Sep 17 00:00:00 2001 From: Mario Buikhuizen Date: Mon, 18 Sep 2023 16:53:03 +0200 Subject: [PATCH] feat: allow frontend code in events --- ipyvue/VueWidget.py | 27 ++++++++++++++++++--------- js/src/VueRenderer.js | 15 +++++++++------ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/ipyvue/VueWidget.py b/ipyvue/VueWidget.py index b417b3b..08e1509 100644 --- a/ipyvue/VueWidget.py +++ b/ipyvue/VueWidget.py @@ -86,18 +86,27 @@ def on_event(self, event_and_modifiers, callback, remove=False): ]: del self._event_handlers_map[existing_event] - self._event_handlers_map[event_and_modifiers] = CallbackDispatcher() - - self._event_handlers_map[event_and_modifiers].register_callback( - callback, remove=remove - ) - - if remove and not self._event_handlers_map[event_and_modifiers].callbacks: + if isinstance(callback, str): + self._event_handlers_map[event_and_modifiers] = callback + else: + self._event_handlers_map[event_and_modifiers] = CallbackDispatcher() + + self._event_handlers_map[event_and_modifiers].register_callback( + callback, remove=remove + ) + + if remove and ( + isinstance(self._event_handlers_map[event_and_modifiers], str) + or not self._event_handlers_map[event_and_modifiers].callbacks + ): del self._event_handlers_map[event_and_modifiers] difference = set(self._event_handlers_map.keys()) ^ set(self._events) if len(difference) != 0: - self._events = list(self._event_handlers_map.keys()) + self._events = { + k: v if isinstance(v, str) else None + for k, v in self._event_handlers_map.items() + } def fire_event(self, event, data=None): """Manually trigger an event handler on the Python side.""" @@ -162,7 +171,7 @@ class VueWidget(DOMWidget, Events): slot = Unicode(None, allow_none=True).tag(sync=True) - _events = List(Unicode()).tag(sync=True) + _events = Dict(None, allow_none=True).tag(sync=True) v_model = Any("!!disabled!!", allow_none=True).tag(sync=True) diff --git a/js/src/VueRenderer.js b/js/src/VueRenderer.js index aff2355..f961f12 100644 --- a/js/src/VueRenderer.js +++ b/js/src/VueRenderer.js @@ -146,7 +146,7 @@ function createAttrsMapping(model) { }, {}); } -function addEventWithModifiers(eventAndModifiers, obj, fn) { // eslint-disable-line no-unused-vars +function addEventWithModifiers(eventAndModifiers, content, slotScopes, obj, fn) { // eslint-disable-line no-unused-vars /* Example Vue.compile output: * (function anonymous() { * with (this) { @@ -164,11 +164,12 @@ function addEventWithModifiers(eventAndModifiers, obj, fn) { // eslint-disable-l * } * ) */ - const { on } = Vue.compile(``) + const { on } = Vue.compile(``) .render.bind({ _c: (_, data) => data, _k: Vue.prototype._k, fn, + ...(slotScopes || {}), })(); return { @@ -177,10 +178,12 @@ function addEventWithModifiers(eventAndModifiers, obj, fn) { // eslint-disable-l }; } -function createEventMapping(model, parentView) { - return (model.get('_events') || []) - .reduce((result, eventAndModifiers) => addEventWithModifiers( +function createEventMapping(model, parentView, slotScopes) { + return Object.entries(model.get('_events') || {}) + .reduce((result, [eventAndModifiers, content]) => addEventWithModifiers( eventAndModifiers, + content, + slotScopes, result, (e) => { model.send({ @@ -241,7 +244,7 @@ function createContent(createElement, model, vueModel, parentView, slotScopes) { const scopedSlots = createSlots(createElement, model, vueModel, parentView, slotScopes); return { - on: { ...createEventMapping(model, parentView), ...slotUseOn(model, slotScopes) }, + on: { ...createEventMapping(model, parentView, slotScopes), ...slotUseOn(model, slotScopes) }, ...model.get('style_') && { style: model.get('style_') }, ...model.get('class_') && { class: model.get('class_') }, ...scopedSlots && { scopedSlots: vueModel._u(scopedSlots) },