When I built an analytic dashboard using Python Dash, I found a problem with the data table. I used dash-bootstrap table component but I didn’t find any documentation about how to implement pagination on the table. Dash actually has a default component called data_table to load data into the table and we can set up the pagination, but I’m not too fond of the Dash data_table style and it’s too hard to modify the table styling.
So I did some research and finally found the solution. I generally use Dash callback to get the active page from dash-bootstrap component and filter the data based on the active page, then load the data into dash-bootstrap table component.
Here’s the step-by-step:
Create a function to get the total page based on page size. I create a constant variable to set page size.
def get_total_page(page_size, total_data):
data_div_page_size = total_data // page_size
data_mod_page_size = total_data % page_size
total_page = data_div_page_size if data_mod_page_size == 0 else (data_div_page_size+1)
return total_page
Create a function to load data into dash-bootstrap table component
def get_student_score_list(scores, counter):
table_header = [
html.Thead(
html.Tr([
html.Th("No."),
html.Th("Math Score"),
html.Th("Reading Score"),
html.Th("Writing Score"),
html.Th("Avg Score"),
])
)
]
table_rows = []
for score in scores:
table_row = html.Tr([
html.Td(counter),
html.Td(score['MathScore']),
html.Td(score['ReadingScore']),
html.Td(score['WritingScore']),
html.Td(score['avg_score']),
])
table_rows.append(table_row)
counter += 1
table_body = [html.Tbody(table_rows)]
table = dbc.Table(table_header + table_body, striped=True, bordered=True, hover=True, className='p-3')
return table
Create table component on Dash layout. Each component table and pagination should have an ID, which we will use on the callback function.
dbc.Row(
[
dbc.Table(id="score-list"),
dbc.Pagination(id="pagination", max_value=get_total_page(PAGE_SIZE, 100), fully_expanded=False),
]
)
Then create the callback function to update data on the table based on the active page in the pagination component.
# load data source
df = pd.read_csv('data/data.csv')
top_100_scores = df.sort_values(by='avg_score', ascending=False).head(100).to_dict('records')
# create callback
@callback(
Output('score-list', 'children'),
Input('pagination', 'active_page'),
)
def update_list_scores(page):
# convert active_page data to integer and set default value to 1
int_page = 1 if not page else int(page)
# define filter index range based on active page
filter_index_1 = (int_page-1) * PAGE_SIZE
filter_index_2 = (int_page) * PAGE_SIZE
# get data by filter range based on active page number
fitler_scores = top_100_scores[filter_index_1:filter_index_2]
# load data to dash bootstrap table component
table = get_student_score_list(fitler_scores, (filter_index_1 + 1))
return table
And here’s the result
Dash data_table has a lot of functionality than dash-bootstrap table component, but if I only need to show the list of the data without any complex interactivity, I will choose to use dash-bootstrap because of the table visual :D
Thank You for reading ^.^
Github source code: https://github.com/yaumianwar/student-exam-score-dashboard