Help Required on Multi Page navigation

Hi All,

I have created a sample multi page app.

In page 2 I’m generating tables based on tab selection, after table is generated and when I navigate to other links i get error as below.

An object was provided as children instead of a component, string, or number (or list of those)

can someone please help or guide me how I can solve this particular issue.

Thanks in advance.

# standard library
import os
import datetime

# dash libs
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table as dt
import dash_daq as daq
import plotly.figure_factory as ff
import plotly.graph_objs as go

# pydata stack
import pandas as pd
import numpy as np
from sqlalchemy import create_engine

# create database
conn = create_engine('sqlite:///')  # using absolute path

# Import app
from app import *


def generate_dashtable(dataframe):
    return dt.DataTable(
        id='mapping_table',
        # data import
        data=dataframe.to_dict("rows"),
        columns=[{"name": i, "id": i} for i in dataframe.columns],
        filter_action="native",
        sort_action="native",
        sort_mode="multi",
        page_action='native',
        page_current=0,
        page_size=100,
        # style table
        style_table={
            'maxHeight': '500px',
            'overflowY': 'scroll',
            'minWidth': '100%',
        },
        # style cell
        style_cell={
            'textAlign': 'center',
            'height': '50px',
            'padding': '2px 22px',
            'whiteSpace': 'inherit',
            'overflow': 'hidden',
            'textOverflow': 'ellipsis',
        },
        # style header
        style_header={
            'fontWeight': 'bold',
            'backgroundColor': 'grey',
            'color': 'white',
        },
        # style filter
        # style data
        style_data_conditional=[
            {
                # stripped rows
                'if': {'row_index': 'odd'},
                'backgroundColor': 'lightgrey'
            },
        ],
    ),


# Menu Function
def menu():
    return html.Div(
        id="app_heading",
        className="class_app_heading",
        children=[
            html.Div(
                id="app_logo",
                children=[
                    html.Img(src='/assets/logo.png')
                ],
            ),
            html.Div(
                id="app-menu",
                className="class_app_menu",
                children=[
                    dcc.Link('Home',
                             href='/home',
                             id='id_page_1',
                             className='',
                             ),
                    dcc.Link('Page 2',
                             href='/page2',
                             id='id_page_2',
                             className='',
                             ),
                ],
            ),
        ],
    )


# Home Page
def content_home():
    return html.Div(
        [
            html.H1('This is Home Page'),
            html.Hr(),
            html.H1('The time is: ' + str(datetime.datetime.now()))
        ],
        className='main_content'
    )


# Page2
def page2():
    return html.Div(
        [
            dcc.Markdown('''
            >Please Select Below tabs as per requirement!
            '''),
            dcc.Tabs(
                id="mapping_tabs",
                className='custom-tabs-container',
                children=[
                    dcc.Tab(label='tab1',
                            value='tab1',
                            selected_className='custom-tab--selected',
                            ),
                    dcc.Tab(label='tab2',
                            value='tab2',
                            selected_className='custom-tab--selected'),
                ],
            ),
            dcc.Loading(
                color='#ff9900',
                children=[
                    html.Div(id='tab_content_div')
                ], ),
        ],
        className='main_content'
    )


def serve_layout():
    return html.Div(
        [
            menu(),
            dcc.Location(id='url', refresh=False),
            dcc.Loading(color='#ff9900',
                        children=[
                            html.Div(id='page-content')
                        ]
                        )
        ]
    )


app.layout = serve_layout()


# Index Callbacks-------------------------------------------------------------------------------------------------------
@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if not pathname is None:
        pathname = pathname.lower()

    if pathname == '/page2':
        return page2()
    elif pathname in ["/", "/home"]:
        return content_home()
    # If the user tries to reach a different page, return a 404 message
    return html.Div(
        [
            html.H1("404: Page Not found", className="text-danger"),
            html.Hr(),
        ]
    )


# Page2 callbacks
@app.callback(
    Output('tab_content_div', 'children'),
    [
        Input('mapping_tabs', 'value')
    ]
)
def render_content(tab):
    if tab == 'tab1':
        sql = 'Select distinct * from table1'
        df = pd.read_sql_query(sql, conn)
        content = generate_dashtable(df)

        return content
    elif tab == 'tab2':
        sql = 'Select distinct * from table2'
        df = pd.read_sql_query(sql, conn)
        content = generate_dashtable(df)

        return content


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


I’m not too familiar with the tabs component, but one candidate I see in your code where a callback should be returning a valid children value but might not be is in render_content, where if the tab value is something other than tab1, or tab2, the function will return None. Maybe try printing the value of tab?

you could also return dash.no_update if you don’t want to update the current children contents if either if condition is not met

Thanks @nedned and @flyingcujo.

I updated the callback, added else condition with no_update. I had to also update tab_content_div with initial div contents

# Page2 callbacks
@app.callback(
    Output('tab_content_div', 'children'),
    [
        Input('mapping_tabs', 'value')
    ]
)
def render_content(tab):
    if tab == 'tab1':
        sql = 'Select distinct * from table1'
        df = pd.read_sql_query(sql, conn)
        content = generate_dashtable(df)

        return content
    elif tab == 'tab2':
        sql = 'Select distinct * from table2'
        df = pd.read_sql_query(sql, conn)
        content = generate_dashtable(df)

        return content
    else:
        # Return without updating page.
        return no_update

issue is resolved for same page refresh(or navigation) but not when I navigate to Home Page.

Should the children content be cleared before navigating to other page layout?