diff --git a/lumen/filters/base.py b/lumen/filters/base.py index 535739f10..7889e8407 100644 --- a/lumen/filters/base.py +++ b/lumen/filters/base.py @@ -63,6 +63,9 @@ class Filter(MultiTypeComponent): def __init__(self, **params): super().__init__(**params) + self._setup_sync() + + def _setup_sync(self): if self._sync_with_url: pn.state.location.sync(self, {'value': self.field}, on_error=self._url_sync_error) @@ -241,6 +244,14 @@ class BaseWidgetFilter(Filter): __abstract = True + def __init__(self, **params): + self.widget = None + super().__init__(**params) + + def _setup_sync(self): + if self._sync_with_url and self.widget is not None: + pn.state.location.sync(self.widget, {'value': self.field}, on_error=self._url_sync_error) + def _url_sync_error(self, values): value = values['value'] if value is self.widget.value: @@ -323,6 +334,7 @@ def __init__(self, **params): self.widget.value = val elif self.default is not None: self.widget.value = self.default + self._setup_sync() @classmethod def _validate_widget(cls, widget: str, spec: Dict[str, Any], context: Dict[str, Any]) -> str: @@ -407,6 +419,7 @@ def __init__(self, **params): value = tuple(self.default) self.widget = widget(name=self.label, options=options, value=value) self.widget.link(self, value='value', visible='visible', disabled='disabled', bidirectional=True) + self._setup_sync() @property def query(self) -> Any: @@ -443,6 +456,7 @@ def __init__(self, **params): self.param.set_param(**param_overrides) self.widget = widget_type(**self._widget_kwargs(as_date=self._as_date)) self.widget.link(self, value='value', visible='visible', disabled='disabled', bidirectional=True) + self._setup_sync() def _widget_kwargs(self, as_date: bool) -> Dict[str, Any]: field_schema = self.schema.get(self.field, {}) diff --git a/lumen/tests/test_dashboard.py b/lumen/tests/test_dashboard.py index 29bec53ef..bd59ed050 100644 --- a/lumen/tests/test_dashboard.py +++ b/lumen/tests/test_dashboard.py @@ -82,11 +82,11 @@ def test_dashboard_with_url_sync_filters(set_root, document): layout = dashboard.layouts[0] f1, f2 = list(layout._pipelines.values())[0].filters f1.value = (0.1, 0.7) - assert pn.state.location.search == '?A=%5B0.1%2C+0.7%5D' + assert pn.state.location.query_params == {'A': [0.1, 0.7], 'C': []} pn.state.location.search = '?A=%5B0.3%2C+0.8%5D' assert f1.value == (0.3, 0.8) f2.value = ['foo1', 'foo2'] - assert pn.state.location.search == '?A=%5B0.3%2C+0.8%5D&C=%5B%22foo1%22%2C+%22foo2%22%5D' + assert pn.state.location.query_params == {'A': [0.3, 0.8], 'C': ['foo1', 'foo2']} pn.state.location.search = '?A=%5B0.3%2C+0.8%5D&C=%5B%22foo1%22%2C+%22foo2%22%2C+%22foo3%22%5D' assert f2.value == ['foo1', 'foo2', 'foo3'] @@ -98,14 +98,14 @@ def test_dashboard_with_url_sync_filters_with_default(set_root, document): layout = dashboard.layouts[0] f1, f2 = list(layout._pipelines.values())[0].filters f1.value = (0.1, 0.7) - assert pn.state.location.search == '?C=%5B%27foo1%27%5D&A=%5B0.1%2C+0.7%5D' + assert pn.state.location.query_params == {'C': ['foo1'], 'A': [0.1, 0.7]} pn.state.location.search = '?A=%5B0.3%2C+0.8%5D' assert f1.value == (0.3, 0.8) assert f2.value == ['foo1'] assert f1.widget.value == (0.3, 0.8) assert f2.widget.value == ['foo1'] f2.value = ['foo1', 'foo2'] - assert pn.state.location.search == '?A=%5B0.3%2C+0.8%5D&C=%5B%22foo1%22%2C+%22foo2%22%5D' + assert pn.state.location.query_params == {'C': ['foo1', 'foo2'], 'A': [0.3, 0.8]} pn.state.location.search = '?A=%5B0.3%2C+0.8%5D&C=%5B%22foo1%22%2C+%22foo2%22%2C+%22foo3%22%5D' assert f2.value == ['foo1', 'foo2', 'foo3'] assert f2.widget.value == ['foo1', 'foo2', 'foo3'] @@ -119,7 +119,7 @@ def test_dashboard_with_url_sync_filters_with_overwritten_default(set_root, docu f1, f2 = list(layout._pipelines.values())[0].filters f1.value = (0.1, 0.7) f2.value = [] # overwriting default with empty list - assert pn.state.location.search == '?C=%5B%5D&A=%5B0.1%2C+0.7%5D' + assert pn.state.location.query_params == {'C': [], 'A': [0.1, 0.7]} assert f2.widget.value == [] @sql_available