[Solved] RadioItems label style change

Hi,

With the current way the RadioItems component is implemented, with the Label as the parent and Input as the child, it is not possible to style the specific label that is checked (and by extension style the unchecked labels).

I found a similar thread regarding this:

In this thread, @chriddyp suggests implementing the .is_checked class, which would work perfectly, but it seems that it is yet to be implemented so I’ll need a workaround.

I’ve found a JS solution, but it’s messy as hell, limited, and I’m really not familiar with JS so would prefer a better solution.
https://codepen.io/anon/pen/Bgozdj
That’s a simplified implementation of what I’m trying to achieve.

Is it possible to output a callback to an internal style sheet, which is hopefully declared after the external style sheet so it takes precedent?

What other solutions are there?

Thanks.

Checkout dash-bootstrap-component (https://dash-bootstrap-components.opensource.faculty.ai/l/components/input) Their radioItems component has a style option available to each option.

1 Like

Lot of nifty looking components there, thanks for the suggestion flyingcujo!

1 Like

one of the drawbacks I discovered is that while options for various components are themselves a component, each needs to be listed as an input to a callback.

Yeah that can be an issue, luckily in my case there are very few options.

Hmm, not sure it’ll help in the end without being annoying, or maybe I’m just not understanding how to implement this correctly.

RadioItems doesn’t seem to extend the functionality enough to allow for styling the individual labels. You can set a style for all the inputs or labels, but not each one (from what I can see).

I tried using RadioButton instead. These seem to function more like checkboxes rather than radio buttons. They can be unchecked, and they are standalone, so I need callbacks to not only maintain the check upon clicking a checked radio button, but also to uncheck other radio buttons upon checking a radio button. I didn’t spend much time on this, but couldn’t figure out how to do this. Seems like a case of looping through all the button IDs with checked as the Input and Outputs except 1 State for the same id as the Output, then setting a conditionals in the function to avoid conflicts.

yeah…I apologize about that…think I sent you down a rabbit hole - at least you learned about the other cool features of this project.

Not at all! It’s definitely a useful project which I wish I knew about earlier. Maybe I can bug them about extending the functionality of RadioItems to include this.

Solved! Somewhat. Thanks to @tcbegley from the following link.

In this case, dash-bootstrap-components isn’t required. Achieved using buttons.

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate

app = dash.Dash(__name__, static_folder="assets")
app.config["suppress_callback_exceptions"]=True

def gen_dash_dep(dep, comp_id, comp_prop):
    if len(comp_prop) == 1:
        comp_prop = comp_prop * len(comp_id)
    return [dep(c[0], c[1]) for c in zip(comp_id, comp_prop)]

app.layout = html.Div([
    html.Button("Day", id="day", disabled=True),
    html.Button("Week", id="week"),
    html.Button("Month", id="month")
    ], className="button-group", id="date-group")

@app.callback(
    gen_dash_dep(Output, ["day", "week", "month"], ["disabled"]),
    gen_dash_dep(Input, ["day", "week", "month"], ["n_clicks"])
)
def toggle_buttons(n_day, n_week, n_month):
    ctx = dash.callback_context
    
    if not ctx.triggered:
        raise PreventUpdate
    else:
        button_id = ctx.triggered[0]["prop_id"].split(".")[0]

    if not any([n_day, n_week, n_month]):
        raise PreventUpdate
    elif button_id == "day":
        return True, False, False
    elif button_id == "week":
        return False, True, False
    elif button_id == "month":
        return False, False, True

if __name__ == "__main__":
    app.run_server(debug=True)

Using the following CSS:

.button-group button {
    border: 1px solid #ccc;
    border-radius: 0px;
    font: bold 11px Roboto, sans-serif;
    padding: 6px 7px;
    background-image: -webkit-linear-gradient(top,#fefefe,#f3f3f3);
    background-image: -moz-linear-gradient(top,#fefefe,#f3f3f3);
    cursor: pointer;
    margin: 0px -1px 0px 0px;
    border-collapse: collapse; }

.button-group button:focus {
    outline:0; }
    
.button-group button:first-child {
    border-radius: 3px 0 0 3px; }

.button-group button:last-child {
    border-radius: 0 3px 3px 0; }
    
.button-group button:hover {
    box-shadow: inset 0px 1px 2px rgba(0,0,0,.2); }

.button-group button:disabled {
    color: black;
    background-image: -webkit-linear-gradient(top,#eee,#e3e3e3);
    background-image: -moz-linear-gradient(top, #eee,#e3e3e3);
    box-shadow: inset 0px 1px 2px rgba(0,0,0,.2);
}
1 Like