roinr
March 17, 2021, 1:14pm
1
I’m trying to add a property to my custom widget that accepts a dictionary.
The dictionary is expected to include css rules in the following structure:
{
<selector>: {<property>: <value>},
...
}
On the python side I defined the property like this:
custom_styles = Dict(String, Dict(String, Either(String, Either(Float, Int))), default=None, help=""""
Additional CSS rules.
""")
On the typescript side:
custom_styles: p.Property<{[key: string]: any} | null>
and
custom_styles: [ Nullable(Dict(String, Dict(String, Or(String, Number)))), null ],
When loading the widget, I get the following error in the console:
The invalid value that’s specified in the error is the value that I set for the property.
Any idea what’s wrong here?
Bryan
March 17, 2021, 5:04pm
2
@roinr That seems fine, offhand. What happens if you loosen the property type to Dict(String, Any)
everywhere, is there still a validation error?
cc @mateusz
roinr
March 17, 2021, 8:12pm
3
yeah…same error.
OS: WSL
Bokeh: v2.2.3
Python: v3.7.10
Bryan
March 17, 2021, 9:12pm
4
Can you provide a Minimal Reproducible Example ? I can’t really speculate further without running real code.
roinr
March 18, 2021, 8:31am
5
@Bryan This should work:
from bokeh.models.widgets.markups import Markup
from bokeh.core.properties import String, Dict, AnyRef
from bokeh.util.compiler import TypeScript
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
render(): void {
super.render()
if (this.model.render_as_text)
this.markup_el.textContent = this.model.text
else
this.markup_el.innerHTML = this.model.text
}
}
export namespace CustomDiv {
export type Attrs = p.AttrsOf<Props>
export type Props = Markup.Props & {
render_as_text: p.Property<boolean>
custom_styles: p.Property<({[key: string]: any} | null)>
}
}
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, Nullable, Dict, String, Any}) => ({
render_as_text: [ Boolean, false ],
custom_styles: [ Nullable(Dict(String, Any)), null ],
}))
}
}
"""
class CustomDiv(Markup):
''' Custom Div widget.
'''
__implementation__ = TypeScript(TS_CODE)
custom_styles = Dict(String, AnyRef, default=None, help=""""
Additional CSS rules.
""")
div = CustomDiv(
text="Hello world!",
custom_styles={"div.bk.bk-clearfix": {"font-size": "30px"}}
)
curdoc().add_root(div)
Bryan
March 18, 2021, 4:41pm
6
@roinr The only way I could make it work was with
custom_styles: [ Nullable(Any), null ],
Note your code above was also missing Nullable
on the Python side. I’d suggest filing a GitHub Issue with the MRE.