Link within page with HTML and css only?

In my app, I have a button that displays several new graphs when clicked. I would like to also automatically scroll down to the html div element containing the new graphs when the button is clicked.

I am looking at this question on stack overflow:

https://stackoverflow.com/questions/24739126/scroll-to-a-specific-element-using-html

When I try this layout

html.A(
dbc.Button(‘Show More’,id=‘show-more-button’),
href=“#more-graphs-container”)
html.Div( id=‘more-graphs-container’ …)

with this for css

html{
scroll-behavior: smooth;
}

The page scrolls to the top when I click the button instead scrolling to the div I want, but the link does change to /#more-graphs-container.

Any ideas?

Hi @syrup

I used Client side callback to move the page using some js code: Clientside Callbacks | Dash for Python Documentation | Plotly

Here is the code that a) move the page down or b) return to Home:

# some client side callback to introduce js code
# This js will move the page down when the users select a Tab other than the first.
app.clientside_callback(               # this is a way to add a client side callback
    """                                 # from here the code is a javascript function
    function(active) {                   # function with any name
        if (active != "tab-0") {        # this is the condition to fire the movement: if the user selects any Tabs (exept the first one
            window.scrollTo(0, 400);    # the windows goes down 400px
            }
    }
    """,
    Output("javascript2", "children"),     # this output can be any component (eg. html.Div)
    Input('main-tabs', 'active_tab'),       # the dcc.Tabs that fires the callback
)


# This js will send the page up (at home) when the dcc.Input (ticker) has changed
app.clientside_callback(
    """
    function(ticker) {                                  # js function
        window.scrollTo(0, 0);                       # the page goes to the top left corner
    }
    """,
    Output("javascript", "children"),             # this line do nothing, could be any component
    Input('input-1-submit', 'value'),              # this is a dcc.Input where the user enters a new Company ticker, its trigger the callback
)

The output component could be anything because is not receiving anything.

2 Likes

Thanks very much Eduardo. Would you be able to send a bit of your relevant app.layout code as well so I could get a better sense of how this is working?

Hey @syrup

There is no relevant information in the layout, I added coments in each line of the code where you can see how it works.

The clientside callback has a particular format, as you can see the output and input are at the end, in this case, because the js code is only to move the page down or to “Home” (0,0) there is nothing to return in the Output. You can create any html.Div() with id to use as Output.

All the code between the “”" are javascript code.
The Input that fires the callback could be any component, in this case the dbc.Tabs that will trigger the callback everytime the user selects a tab or a dcc.Input that will trigger the callback when the users selects a new company to see.

Thank you for elaborating!

I am getting this error: “Cannot read property ‘children’ of undefined”

This is my clientside callback:

app.clientside_callback(
    """
    function(n_clicks) {
        if n_clicks == None{
            raise PreventUpdate;
        }
        else{
            window.scrollTo(0, document.body.scrollHeight);
        }

    }
    """,
    Output("javascript", "children"),
    Input('try-another-button', 'n_clicks'),
)

and this is my layout:

html.Div(id='javascript'),
html.A(dbc.Button('Try another city',id='try-another-button'),href="/")

Do you have any suggestions for how to fix this? I want the page to reload and then scroll to the bottom of page when the “try again” button is clicked.

raise PreventUpdate is Python code, I’m not sure what the equivalent is in Javascript?

Hi @syrup

I’m receiving the same message :thinking:, I think there is not neccessary to use preventUpdate when the input is a button, because the callback do not trigger without any user action. althoght I get the same error if I exclude the preventUpdate.

This code has your input and output components, and works, just use it and see if you get the alert message, then change the alert for the movement you need:

app.clientside_callback(
    """
    function(n_clicks) {
    
        if (n_clicks > 0) {       
            alert("It Works");   
            }
    }
    """,
    Output("javascript", "children"),
    Input('try-another-button', 'n_clicks'),
)