@Bryan Thanks for the reply and sorry for the delay.
My question is whether it’s possible to set the default value of a property based on the value of a different property?
Let’s say we have created a custom Div widget. This widget has two properties (other than the ones it inherits): words and select_all. words is just a list of strings. select_all controls whether all the words in the list will be displayed (True) or just the first word (False). In the provided MRE, I set the select_all to True and I expect that the widget will set the value of text to Hello World automatically. In order to check this behavior, I added a button that changes the text. The on_change callback then prints the old and new values of the text property. The expected behavior is that the old value will be “Hello World” since the select_all was set to True. As you can see, my attempt was to silently set the text based on the value of select_all in the initialize method which obviously doesn’t work but I do want to change text silently since this should be its initial value and shouldn’t invoke the callback.
MRE:
from bokeh.models.layouts import Column
from bokeh.models.widgets.markups import Markup
from bokeh.core.properties import String, List, Bool
from bokeh.util.compiler import TypeScript
from bokeh.models import Button
from bokeh.io import curdoc
TS_CODE = """
import {Markup, MarkupView} from "models/widgets/markup"
import * as p from "core/properties"
export class CustomDivView extends MarkupView {
model: CustomDiv
initialize(): void {
super.initialize()
super.render()
const initText = this.model.select_all ? this.model.words.join(' ') : this.model.words[0];
this.model.setv({text: initText}, {silent: true})
}
render(): void {
super.render()
this.markup_el.textContent = this.model.text
}
}
export namespace CustomDiv {
export type Attrs = p.AttrsOf<Props>
export type Props = Markup.Props & {
words: p.Property<string[]>
select_all: p.Property<boolean>
}
}
export interface CustomDiv extends CustomDiv.Attrs {}
export class CustomDiv extends Markup {
properties: CustomDiv.Props
__view_type__: CustomDivView
constructor(attrs?: Partial<CustomDiv.Attrs>) {
super(attrs)
}
static init_CustomDiv(): void {
this.prototype.default_view = CustomDivView
this.define<CustomDiv.Props>(({Boolean, String, Array}) => ({
words: [ Array(String), [] ],
select_all: [ Boolean, false ],
}))
}
}
"""
class CustomDiv(Markup):
''' Custom Div widget.
'''
__implementation__ = TypeScript(TS_CODE)
words = List(String, default=[], help="""
List of words.
""")
select_all = Bool(default=False, help="""
Displays all the words in the list.
""")
div = CustomDiv(words=["Hello", "World"], select_all=True)
b = Button(label="change text")
def on_change(attr, old, new):
print(f"old: {old},", f"new: {new}")
def on_click(event):
div.text = "Hello"
div.on_change('text', on_change)
b.on_click(on_click)
curdoc().add_root(Column(div, b))