Highlight the active/current (pressed) button

Hy guys. I am trying to highlight the active/current (pressed) button like it was done on https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_active_element. I am not geting same results, the button doesn’t stay active, only hover effect is present. Does anyone have idea why?

Here is my Dash code:

import dash
import dash_html_components as html

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]

app = dash.Dash(name, external_stylesheets=external_stylesheets)

app.layout = html.Div([

    html.Div([
        html.Button('Button 1', id='btn-1',className="btn"),
        html.Button('Button 2', id='btn-2',className="btn active"),
        html.Button('Button 3', id='btn-3',className="btn"),
       
],id="myDIV")

])

if name == ‘main’:
app.run_server(debug=True)

Here is my css code:

.btn {
background-color: #f1f1f1;
}

/* Style the active class, and buttons on mouse-over */
.active, .btn:hover {
background-color: #666;
color: white;
}

Here is my js code:

var header = document.getElementById(“myDIV”);
var btns = header.getElementsByClassName(“btn”);
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener(“click”, function() {
var current = document.getElementsByClassName(“active”);
current[0].className = current[0].className.replace(" active", “”);
this.className += " active";
});
}

I am keeping .css and .js files in assets folder.

I’m not quite sure why your attempt isn’t working, but if it’s helpful I was able to achieve what you’re trying to do with a callback instead of JavaScript. Something like this:

import dash
import dash_html_components as html
from dash.dependencies import Input, Output

external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div(
    [
        html.Div(
            [
                html.Button("Button 1", id="btn-1", className="btn"),
                html.Button("Button 2", id="btn-2", className="btn active"),
                html.Button("Button 3", id="btn-3", className="btn"),
            ],
            id="myDIV",
        )
    ]
)


@app.callback(
    [Output(f"btn-{i}", "className") for i in range(1, 4)],
    [Input(f"btn-{i}", "n_clicks") for i in range(1, 4)],
)
def set_active(*args):
    ctx = dash.callback_context

    if not ctx.triggered or not any(args):
        return ["btn" for _ in range(1, 4)]

    # get id of triggering button
    button_id = ctx.triggered[0]["prop_id"].split(".")[0]

    return [
        "btn active" if button_id == f"btn-{i}" else "btn" for i in range(1, 4)
    ]


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

You might have to do a bit of playing around to get the initial state right. At the moment I have it so that no button is active to begin with.

Thanks a lot, this will do a job. If someone finds out why my code doesn’t work please let me know.

Because Dash is building a React application, you can’t use regular JavaScript to interact with it.

Read more here: https://dash.plot.ly/react-for-python-developers and here: Build Your Own Components | Dash for Python Documentation | Plotly

Hi tcbegley, do you know how to implement this in R? I had the question a long time and finally found your solution. But I don’t know how to carry that over to R.

Not sure I’m afraid, I haven’t played around with dashR all that much. The section “How do I determine which Input has changed” here in the docs should help. You can get a similar callback context object by doing something like ctx <- app$callback_context(). Then it’s just a case of figuring out which button was last clicked and setting the classnames appropriately. In my example above I used a few Pythonic things like list comprehensions and *args so I didn’t have to think about the number of function arguments, but the logic is pretty generic.