Skip to content

Commit

Permalink
fix: watch didn't work for Vue-only vars
Browse files Browse the repository at this point in the history
  • Loading branch information
iisakkirotko committed Dec 6, 2023
1 parent 459ae46 commit 828c11d
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 19 deletions.
38 changes: 19 additions & 19 deletions js/src/VueTemplateRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,27 +163,27 @@ function addModelListeners(model, vueModel) {
}

function createWatches(model, parentView, templateWatchers) {
return model.keys()
.filter(prop => !prop.startsWith('_')
&& !['events', 'template', 'components', 'layout', 'css', 'data', 'methods'].includes(prop))
.reduce((result, prop) => ({
...result,
[prop]: {
handler(value) {
if (templateWatchers && templateWatchers[prop]) {
templateWatchers[prop].bind(this)(value);
}
/* Don't send changes received from backend back */
if (_.isEqual(value, model.get(prop))) {
return;
}
const modelWatchers = model.keys().filter(prop => !prop.startsWith('_')
&& !['events', 'template', 'components', 'layout', 'css', 'data', 'methods'].includes(prop))
.reduce((result, prop) => ({
...result,
[prop]: {
handler(value) {
if (templateWatchers && templateWatchers[prop]) {
templateWatchers[prop].bind(this)(value);
}
/* Don't send changes received from backend back */
if (_.isEqual(value, model.get(prop))) {
return;
}

model.set(prop, value === undefined ? null : _.cloneDeep(value));
model.save_changes(model.callbacks(parentView));
},
deep: true,
model.set(prop, value === undefined ? null : _.cloneDeep(value));
model.save_changes(model.callbacks(parentView));
},
}), {});
deep: true,
},
}), {})
return {...templateWatchers, ...modelWatchers};
}

function createMethods(model, parentView) {
Expand Down
94 changes: 94 additions & 0 deletions tests/ui/test_watchers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import pytest
import sys
from playwright.sync_api import Page
from traitlets import Callable, Int, Unicode, default
from IPython.display import display

if sys.version_info < (3, 7):
pytest.skip("requires python3.7 or higher", allow_module_level=True)

import ipyvue as vue


class WatcherTemplateTraitlet(vue.VueTemplate):
number = Int(0).tag(sync=True)
callback = Callable()
text = Unicode("Click Me ").tag(sync=True)

@default("template")
def _default_vue_template(self):
return """
<template>
<div @click="number += 1">{{text + number}}</div>
</template>
<script>
export default {
watch: {
number: function(value) {
callback();
}
}
}
</script>
"""

def vue_callback(self):
self.callback()


# We test that the watcher is activated when a var from python is changed
def test_watcher_traitlet(solara_test, page_session: Page):
def callback():
widget.text = "Clicked "

widget = WatcherTemplateTraitlet(callback=callback)

display(widget)

widget = page_session.locator("text=Click Me 0")
widget.click()
widget = page_session.locator("text=Clicked 1")


class WatcherTemplateVue(vue.VueTemplate):
callback = Callable()
text = Unicode("Click Me ").tag(sync=True)

@default("template")
def _default_vue_template(self):
return """
<template>
<div @click="number += 1">{{text + number}}</div>
</template>
<script>
export default {
watch: {
number: function(value) {
callback();
}
},
data(){
return {
number: 0
}
}
}
</script>
"""

def vue_callback(self):
self.callback()


# We test that watch works for a purely Vue variable
def test_watcher_vue(solara_test, page_session: Page):
def callback():
widget.text = "Clicked "

widget = WatcherTemplateVue(callback=callback)

display(widget)

widget = page_session.locator("text=Click Me 0")
widget.click()
widget = page_session.locator("text=Clicked 1")

0 comments on commit 828c11d

Please sign in to comment.