Ad

How To Render A CheckboxGroup (or Any Other Element) In A Custom Way?

- 1 answer

Bokeh renders the checkboxes like this

<div class="bk-bs-checkbox">
    <label>
        <input type="checkbox" value="0">
        Label text
    </label>
</div>

But I would like to select the label depending on the input state :focus, :disabled, :checked, ...

Since there is no CSS parent selector, what I could do to render the checkbox in a custom way? I would like to avoid JavaScript. If the checkbox is rendered as the following code it would be easier to customize:

<div class="bk-bs-checkbox">
    <input type="checkbox" value="0">
    <label>
        Label text
    </label>
</div>

And I could this CSS code to select the label depending the checkbox state:

.bk-bs-checkbox input[type="checkbox"]:disabled + label::after {
    background-color: red,
}

This is just an example to show one case of use.

Is there an easy way to achieve this? Actually I am looking for some mechanism in bokeh to inherit the template that renders that object in order to change it with my custom template.

Ad

Answer

Well, finally I have found a workaround that is not very clean, but it works. Basically I have hidden the original element and I have created my own customised control. I have used JavaScript as @Gerard suggested.

  1. First I need to wait until Bokeh Server is loaded. All the elements must be already rendered. So I have applied some workaround from this answer

  2. Then I have hidden the original element generated by bokeh using the python attribute css_classes and the CSS tyle display: none;

  3. I have created the element by JavaScript (actually I have enabled jQuery). This can be done with bokeh templates as well. In my case I found it more convenient like this. Then I have added the element before the original one.

    var new_cb = $('<div>', {
        class: 'abc-checkbox abc-checkbox-primary',
    });
    new_cb.append(
        $('<input>', {
            id: 'id_new_cb',
            type: 'checkbox'
        })
    );
    new_cb.append(
        $('<label>', {
            for: 'id_new_cb',
            text: 'Custom element'
        })
    );
    $('.original_cb').before(new_cb);
    
  4. Finally I have added an event to trigger the event on the original hidden element:

    $('#id_new_cb').change(function() {
        if(this.checked) {
            $('.original_cb input').click();
        } else {
            $('.original_cb input').click();
        }
    });
    

Something similar can be done with the rest of the elements. This is useful if you just want to change a couple of elements. If not this will become kind of cumbersome.

Ad
source: stackoverflow.com
Ad