When using state.location.sync() came across a bit of an issue when the url would contain something like
my_var=2
But the intention would be to interpret my_var as a string item, say within a TextInput widget.
The 2 would be converted from the url string to an integer and then when attempting to map within panel.io.location it would refuse.
Thus made the following tweak within panel.io.location (starting at line 167):
def _update_synced(self, event: param.parameterized.Event = None) -> None:
if self._syncing:
return
query_params = self.query_params
for p, parameters, _, on_error in self._synced:
mapping = {v: k for k, v in parameters.items()}
mapped = {}
for k, v in query_params.items():
if k not in mapping:
continue
pname = mapping[k]
try:
v = p.param[pname].deserialize(v)
except Exception:
pass
try:
equal = is_equal(v, getattr(p, pname))
except Exception:
equal = False
if not equal:
if not isinstance(v, type(p.param.value.default)):
# Sometimes the url is converted into a numeric,
# whereas we want to retain a string type, this
# approach should retain that
try:
v = type(p.param.value.default)(v)
except Exception:
# Unable to convert, this will likely lead to a non
# application of the sync. Could pass and let
# existing on_error callback deal with:
# pass
# Or can invoke the callback now
if on_error:
on_error({k: v})
else:
pass
mapped[pname] = v
try:
p.param.update(**mapped)
except Exception:
if on_error:
on_error(mapped)
Basically, checking does the interpreted type match the default of the widget, if not, attempt to cast to the widget type before trying to push the update.