Is it possible to return a different layout to the same Output in plotly

This was just assuming the pathnames were numbers, you could use something like @AIMPED.

from collections import deque

page_paths = deque([page['path'] for page in dash.page_registry.values() if page['name'] != 'Not found 404'])
import dash
from dash import Dash, dcc, html, Input, Output, State, no_update, ctx
import dash_bootstrap_components as dbc


# region Card definition

def first_card():
    return dbc.Card(
        html.Div('This is picture 1'),
        className="text-center text-nowrap my-2 p-2",
    )


def second_card():
    return dbc.Card(
        html.Div('This is picture 2'),
        className="text-center text-nowrap my-2 p-2",
    )


def third_card():
    return dbc.Card(
        html.Div('This is picture 3'),
        className="text-center text-nowrap my-2 p-2",
    )


cards = ['/', '/2', '/3']

# endregion

app = Dash(__name__, external_stylesheets=[dbc.themes.SUPERHERO, dbc.icons.BOOTSTRAP],
           pages_folder='', use_pages=True)
interval = dcc.Interval(interval=5000)
buttons = html.Div([html.Button(id='prev', className='bi bi-arrow-left-square'),
                    html.Button(id='pause', className='bi bi-pause-btn'),
                    html.Button(id='play', className='bi bi-play-btn', disabled=True),
                    html.Button(id='next', className='bi bi-arrow-right-square')])
app.layout = dbc.Container([interval, buttons, dash.page_container])

dash.register_page('1', path='/', layout=first_card)
dash.register_page('2', path='/2', layout=second_card)
dash.register_page('3', path='/3', layout=third_card)

from collections import deque

page_paths = deque([page['path'] for page in dash.page_registry.values() if page['name'] != 'Not found 404'])


@app.callback(
    Output('_pages_location', 'href'),
    Input(interval, "n_intervals"),
    State('play', 'disabled'),
    State('_pages_location', 'pathname'),
    prevent_initial_call=True)
def update_cards(n_intervals, v, pathname):
    if not v:
        return no_update
    page_paths.rotate(-1)
    return page_paths[0]

@app.callback(
    Output('_pages_location', 'href', allow_duplicate=True),
    Input('prev', "n_clicks"),
    Input('next', "n_clicks"),
    State('_pages_location', 'pathname'),
    prevent_initial_call=True)
def update_cards_buttons(n1, n2, pathname):
    if ctx.triggered_id == 'prev':
        page_paths.rotate(1)
    else:
        page_paths.rotate(-1)
    return page_paths[0]

@app.callback(
    Output('pause', 'disabled'),
    Output('play', 'disabled'),
    Input('pause', 'n_clicks'),
    prevent_initial_call=True
)
def pause(n1):
    return True, False

@app.callback(
    Output('pause', 'disabled', allow_duplicate=True),
    Output('play', 'disabled', allow_duplicate=True),
    Input('play', 'n_clicks'),
    prevent_initial_call=True
)
def play(n1):
    return False, True


if __name__ == "__main__":
    app.run_server(port=7676, debug=True)
2 Likes

As always you provide extraordinarily detailed answers my beloved companion at plotly

1 Like

Ok still on the same project need to add some modifications to it. I would like some help. So far I have updated the project with internal data so I can t post it here. The challenge that Im having is, when a card is paused it does not up date the live card with new data even though the interval is updating the page. How do I use intervals to update independent pages in multi-page.

from pages import FirstCard, SecondCard, ThirdCard
from dash import Dash, dcc, html, Input, Output, State, no_update, ctx
import dash_bootstrap_components as dbc
import dash

cards = ['/', '/2', '/3']

app = Dash(__name__, external_stylesheets=[dbc.themes.SUPERHERO, dbc.icons.BOOTSTRAP],
           pages_folder='', use_pages=True)

interval = dcc.Interval(interval=7000)

buttons = html.Div([html.Button(id='prev', className='bi bi-arrow-left-square'),
                    html.Button(id='pause', className='bi bi-pause-btn'),
                    html.Button(id='play', className='bi bi-play-btn', disabled=True),
                    html.Button(id='next', className='bi bi-arrow-right-square')])

app.layout = dbc.Container([interval,
                            dash.page_container,
                            buttons])

dash.register_page('1', path='/', layout=FirstCard.first_card())
dash.register_page('2', path='/2', layout=SecondCard.second_card())
dash.register_page('3', path='/3', layout=ThirdCard.third_card())


@app.callback(
    Output('_pages_location', 'href'),
    Input(interval, "n_intervals"),
    State('play', 'disabled'),
    State('_pages_location', 'pathname'),
    prevent_initial_call=True)
def update_cards(n_intervals, v, pathname):
    if not v:
        return no_update
    i = pathname.replace('/', '')
    # sets i to current page location
    if not i:
        i = 0
    else:
        i = int(i) - 1
    i += 1
    i = i % len(cards)
    return cards[i]

@app.callback(
    Output('_pages_location', 'href', allow_duplicate=True),
    Input('prev', "n_clicks"),
    Input('next', "n_clicks"),
    State('_pages_location', 'pathname'),
    prevent_initial_call=True)
def update_cards_buttons(n1, n2, pathname):
    i = pathname.replace('/', '')
    # sets i to current page location
    if not i:
        i = 0
    else:
        i = int(i) - 1
    if ctx.triggered_id == 'prev':
        # set that page back, -1 = last in the page list
        i -= 1
    else:
        i += 1
        # loops 3 => 0
        i = i % len(cards)
    return cards[i]

@app.callback(
    Output('pause', 'disabled'),
    Output('play', 'disabled'),
    Input('pause', 'n_clicks'),
    prevent_initial_call=True
)
def pause(n1):
    return True, False
@app.callback(
    Output('pause', 'disabled', allow_duplicate=True),
    Output('play', 'disabled', allow_duplicate=True),
    Input('play', 'n_clicks'),
    prevent_initial_call=True
)
def play(n1):
    return False, True


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