Access Cookie In Serve Layout Function

Hello everyone,

I am trying to initally populate a dropdown in my layout with a cookie. If a user has populated the dropdown with 20 items from their last visit, I would like them to be able to pickup where they left off. I am storing my cookies in the callback context as specified here.

@app.callback(Output('dropdown_container', 'value'),
             [Input('someothercomponent', 'clickData')])
def update_dropdown(clickData):
   #do something
   dash.callback_context.response.set_cookie(
            'mycookie', pickle.dumps(values)) 
   return values
       

I also have a dynamically loaded layout on refresh.

def get_dropdown():
    ...setup options from data...

    dd = dcc.Dropdown(
        id='dropdown_container',
        options=countries+provinces+state+counties,
        value=['worldwide', 'COUNTRY_US:NONE', 'STATE_New York:US'],
        multi=True,
        style={'position': 'relative', 'zIndex': '3', 'font-size': '75%'}
    )
    return dd

def serve_dash_layout():
    return html.Div(id='root-container', children=get_dropdown())


server = flask.Flask(__name__)
app = dash.Dash(server=server,
                meta_tags=get_meta())
app.layout = layouts.serve_dash_layout

Because the function get_dropdown() which is under serve_dash_layout creates the initial dropdown default values, I was wondering if it could have access to the mycookie that I setup in the callback the nexttime the user comes to my app. What global variables does serve_dash_layout have access to?

Thanks so much,
J

+1 having the same issue

For anyone else stumbling across this, I ended up finding this solution: https://github.com/plotly/dash-recipes/blob/master/dash_requests.py

This allows you to pull of any cookies inside of callbacks.

So, just to complete this post with all the information that I was looking as well:

  1. to set cookies

     dash.callback_context.response.set_cookie('mycookie', myvalue)
    
  2. to retrieve the cookie that was set
    . . .
    import flask
    allcookies=dict(flask.request.cookies)
    if ‘mycookie’ in allcookies:
    myvalue=allcookies[‘mycookie’] # I was unable to indent this…:frowning:

Thanks to all

Hi,
thanks for sharing your solution!

Could someone tell me how I can set the cookie’s attribute’s “samesite”=“None” and “secure”=“true”?

I have to do this since I am embedding my application in an iFrame because currently they are not visible anymore once the application is embedded in an iFrame…

Any suggestions are welcome as I am looking for a solution to this for some time…

Thanks!

Hi,

did you come across a solution for this?

thx

Just wanted to reply here with a solution that has worked for me. My use case was having to access a cookie as part of an authentication process with my dash app. To do this, I had to set a dcc.Interval to trigger a clientside callback on the initial page load. In my use case, I needed to store the cookie in a dcc.Store, so that’s what the output of the clientside_callback goes to. The code is below, no guarantees, but hopefully this saves somebody from also spending a week looking for a solution.

app.clientside_callback(
    """
    function(n_intervals) {
        function getCookie(name) {
            let cookieArr = document.cookie.split(";");
            for (let i = 0; i < cookieArr.length; i++) {
                let cookiePair = cookieArr[i].split("=");
                if (name == cookiePair[0].trim()) {
                    return decodeURIComponent(cookiePair[1]);
                }
            }
            return null;
        }
        
        let my_cookie = getCookie('MY-COOKIE-NAME')
        
        if (my_cookie) {
            return { 'my_cookie': my_cookie };
        } else {
            return null;
        }
    }
    """,
    Output('cookie_store', 'data'),
    Input('fetch-cookie-interval', 'n_intervals')

Hello @dataman,

Welcome to the community!

You should be able to do this by converting the layout to a function:

def layout():
   if not flask.request:
       return html.Div() ## this keeps the first initialization happy
   layout = html.Div([
      dcc.Store(id='cookie-store', 
          data={'my_cookie': flask.request.cookies.get('MY-COOKIE-NAME', '')}
        )
      ])
   return layout

This should work for accessing a cookie in the layout when there is a cookie present, now if you need to set a cookie, you can utilize some of the above.

1 Like