So your example isn’t fully complete since I can’t see what self._boutonSaveFinish does. If I provide my own callback it does get called, but as you point out that doesn’t happen until after the JS callback is triggered. For now using the HTML pane is indeed probably your best bet, in the longer term we will add support for a Bokeh DataModel which will let you sync arbitrary attribute changes with the frontend and trigger JS callbacks.
my exemple could not be run like this indeed . I will update the example with something like nghenzi2019 used, because here, what does the self._butonSaveFinish is not a big deal.
I had something similar to do and have a solution perhaps less convoluted if the python call is changing an attribute of a bokeh model.
So there is no unused elements.
In this example, the python callback empties the text input ; while the javascript callback focus on the text input. The latter does so only once the text input is correctly emptied, not before.
import panel as pn
import param
pn.extension()
pn.__version__
val_button = pn.widgets.Button(name = 'Focus once empty',
button_type='primary',
height_policy = 'fit',
)
class TextInput_with_name(pn.widgets.TextInput):
"""
Subclass to add name attribute and find bokehjs model
"""
_name = param.String(default='')
_rename = pn.widgets.TextInput._rename.copy()
_rename.update({'_name': 'name'})
txt = TextInput_with_name(name='Input here', value='I shall be removed', _name='txtinput')
def empty_text_func(event):
"""remove text"""
txt.value = ''
val_button.on_click(empty_text_func)
val_button.jscallback(clicks = """
let txt_element = document.getElementsByName(txt.name)[0]
function focus_only_when_text_empty() {
if(txt.value!=='') {//if not empty
setTimeout(focus_only_when_text_empty, 50);//recheck in 50 milliseconds
return;
}
txt_element.focus();//focus only when empty
}
focus_only_when_text_empty();
""",
args={'txt':txt})
mylist = pn.Row(val_button, txt)
mylist.show()