Switch fontawesome icons using callback

Hello everyone,

I’m trying to simply animate a sidebar toggle icon using a dash callback. The arrwos are just supposed to switch its direction from left to right, when the sidebar is collapsed.
I’m using fontawesome icons by referencing to classnames inside an html i tag.
I’ve noticed that it won’t update the way I wrote my code.

html.Div(
   html.Button(
      html.I(className='fas fa-angle-double-left', id='sidebar-toggle-icon'),
      id='sidebar-toggle'
   ),
id='sidebar'
)

@callback(
    output=(Output('sidebar', 'className'), Output('sidebar-toggle-icon', 'className')),
    inputs=dict(n=Input('sidebar-toggle', 'n_clicks')),
    state=dict(sidebar_current_classname=State('sidebar', 'className'))
)
def toggle_sidebar(n, sidebar_current_classname):
    if sidebar_current_classname == '':
        return 'collapsed', 'fas fa-angle-double-right'

    return '', 'fas fa-angle-double-left'

I’m thinking that there is an issue rendering the icon under the hood, just by switching the classname of the html.I component. I’m asking you guys for information about the origin of this problem and a possible workaround.

Tanks a lot!

When I’m trying to remove the html.I component completely by editing the callback and delivering an emty list to the children attribute of html.Button it throws this error:

Failed to execute ‘removeChild’ on ‘Node’: The node to be removed is not a child of this node.

I’m slowly wondering if it’s even possible to switch an icon in dash like this.

Hi @robinmue - welcome to the Dash community :slightly_smiling_face:

It’s absolutely possible to switch an icon in a callback like this. And your code works perfectly!

btw - nice use of some of the new features in Dash 2.0 such as @callback (instead of @app.callback) and the new flexible callback signatures

Here is a complete MWE that I ran based on your post:
arrow_icon_flip


from dash import Dash, html, Input, Output, State, callback
import dash_bootstrap_components as dbc

app = Dash(
    __name__, external_stylesheets=[dbc.themes.BOOTSTRAP, dbc.icons.FONT_AWESOME]
)
app.layout = dbc.Container(
    html.Div(
        html.Button(
            html.I(className="fas fa-angle-double-left", id="sidebar-toggle-icon"),
            id="sidebar-toggle",
        ),
        id="sidebar",
    )
)


@callback(
    output=(Output("sidebar", "className"), Output("sidebar-toggle-icon", "className")),
    inputs=dict(n=Input("sidebar-toggle", "n_clicks")),
    state=dict(sidebar_current_classname=State("sidebar", "className")),
)
def toggle_sidebar(n, sidebar_current_classname):
    if sidebar_current_classname == "":
        return "collapsed", "fas fa-angle-double-right"
    return "", "fas fa-angle-double-left"


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

2 Likes

Thanks for your time! I might have gotten something else wrong.