I’d like to be able to clear the text that is shown in the TextInput widget. My use case involves sliders: I have a slider plus 2 TextInput boxes to optionally set upper and lower limits. If the user uses these boxes, the slider limits are set to them; if the user then uses the slider itself to change the limits again, I’d like to be able to clear out the text that’s displayed in the TextInput boxes.
I feel like I should clarify that when I suggested
if new == "": return
it was not intended as a workaround or anything I would consider hacky. It’s the correct and appropriate way to handle this use case.
I hope a little context might shed light on why things are best as they are. As it is, the operation of callbacks is completely uniform and can be explained in once succinct statement:
Callbacks fire any time a Bokeh model property changes.
I hope everyone agrees that going from "foo" to "" constitutes a change. Additionally, all users, including the ones who do want to do something when the value is the empty string, can satisfy their needs. Contrast if we start adding special cases:
Callbacks fire any time a Bokeh model property change. Except for these special properties on these modes, that all each behave in these special different ways: .
…
…
…
Now the only way to know for sure what the behavior of a model actual is, is to dig through reference documentation. But worse, there is now an arbitrary limitation on capability that means that any users who do want to respond to the empty string no longer have any recourse to do so.
Well, in my case, there are often non-empty values set to the input box. Like pre-defined standards, the last syntactical correct user input, messages like “Input this and that…” if the box is empty, and various other cases.
Would you consider the approach I posted above as a “non-hacky” and correct/appropriate way as well or could you suggest a better solution?
Based on your way, I also thought about defining a list of strings that would yield in a direct return, like
if new in predefined_strings: return
However this would also ignore user input in some of the cases mentioned at the beginning.
do not end in endless callback loops but is only triggered one additional time.
So foo gets executed twice if the user changes the value in the input box.
Often enough, I’m also ok with this, since the execution is very fast and it does not matter if it runs once or twice, but of course in general leaving it like this is not a good style
The public APIs are public, so if that suits your need, then it suits your need. I don’t really have an opinion on that. I only wanted to challenge the notion that ignoring empty string changes is somehow bad.
If you wanted to tidy things up you might consider making a simple context manager (untested, just a rough idea)
import contextlib
@contextlib.contextmanager
def silenced(model, attr, callback):
model.remove_on_change(attr, callback)
yield model
model.on_change(attr, callback)
with silenced(model, 'foo', cb):
# do stuff