How to hide scrollbar in Plotly Dash Table - python

I have table with a large number of rows, and I want to show everything inside my app.
By default, dash_table.DataTable adds a scrollbar when the table is too long. I would like to remove that scrollbar.

Let's say you have the following application, where the height is set to 300px and overflow is automatic:
import dash
import dash_table
import dash_html_components as html
import pandas as pd
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/1962_2006_walmart_store_openings.csv"
)
app = dash.Dash(__name__)
table = dash_table.DataTable(
id="table",
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict("records"),
style_table={"height": "300px", "overflowY": "auto"},
)
app.layout = html.Div([html.H1("Header"), table, html.Button("Click here")])
if __name__ == "__main__":
app.run_server(debug=True)
You will get this resulting app:
In your case, you want to hide the scroll bar. You might be tempted to change the style_table to:
style_table={"height": "300px", "overflowY": "show"}
Although the entire table will be shown, this unfortunately means the button will be hidden since the table is overflowing beyond the designated height:
So the correct change is to simply set the height of the table to be unlimited:
style_table={"height": None}
And the button will show up correctly:
Controlling the height of the table is thoroughly documented in Dash Table docs. It will show you different ways to use overflowY.

add this argument into dash_table.DataTable:
virtualization=False
and you don't need to touch the height

Related

Why is my Dash callback not being triggered?

I am designing a Dash application using Python.
When a main button is pressed, a smaller sub-button should appear. When this sub-button is pressed, a count keeping track of the number of times it has been pressed must be incremented.
Whenever the main button is pressed, another sub-button should be created with the same functionality as the first sub-button.
Only the latest sub-button that has been created works. It seems like the callback has not been triggered for the others. Any ideas on how to fix this are much appreciated.
I am using callbacks to perform this functionality.
Here is a screenshot of the web application
This is the related code
import base64
import os
from urllib.parse import quote as urlquote
from flask import Flask, send_from_directory
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output,State
import dash_bootstrap_components as dbc
import uuid
server = Flask(__name__)
app = dash.Dash(
server=server,
external_stylesheets=[dbc.themes.BOOTSTRAP]
)
class_card_list = []
class Card:
layout = [
html.Div(id = f"s_1"),
html.Button("Enter anything",id = f"b_one",n_clicks=0)
]
#app.callback(
Output(f"s_1","children"),
Input(f"b_one","n_clicks")
)
def a(n_1):
return f"Button one has been clicked {n_1} times"
app.layout = html.Div(id = "container",children=[
dbc.Button("Press Here",id = "button_1",style={"width":"10vw"},n_clicks=0),
html.Hr(),
])
#app.callback(
Output("container","children"),
Input("button_1","n_clicks"),
State("container","children")
)
def more_classes(n_clicks,old_output):
class_card = Card()
class_card_list.append(class_card)
return old_output + class_card.layout
if __name__ == "__main__":
app.run_server(debug=True, port=8888)
For what I know callbacks aren't for manipulated DOM, probably to get effect you want you have to write JS scripts to hide/unhide object you want.

Retrieve Hex or RGB values from Bootswatch theme via python/dash

I am currently creating a dashboard using dash with figures using plotly. I am using the bootswatch themes (https://bootswatch.com/) with bootstrap components to style the dashboard and I was wondering if there was a way to retrieve the primary, secondary, success etc. colours into either RGB or HEX so that I don't have to hard code it in and can then parse these into plotly functions to style the graphs in the same theme.
As of writing this there isn't a way to do it with Python only.
A dash bootstrap components theme is just a uri pointing to a stylesheet.
>>> dbc.themes.BOOTSTRAP
https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css
For the stylesheets in external_stylesheets link elements are generated and added to the document.
So there isn't a property on a theme or on the app that holds the value of the css variables.
A workaround solution is to use clientside callbacks:
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Output, Input
import dash_bootstrap_components as dbc
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([dcc.Store(id="intermediate-store"), dcc.Store(id="color-store")])
app.clientside_callback(
"""
function(val) {
const bodyStyles = window.getComputedStyle(document.body);
return {
primary: bodyStyles.getPropertyValue("--primary"),
secondary: bodyStyles.getPropertyValue("--secondary"),
success: bodyStyles.getPropertyValue("--success"),
};
}
""",
Output("intermediate-store", "data"),
Input("intermediate-store", "data"),
)
#app.callback(
Output("color-store", "data"),
Input("intermediate-store", "data"),
)
def update_output_div(data):
# data equals: {'primary': '#007bff', 'secondary': '#6c757d', 'success': '#28a745'}
return data
if __name__ == "__main__":
app.run_server(debug=True)
So the idea in the code above is to use Javascript in clientside callbacks to retrieve the css variables and store them in an intermediate Store. When it's stored we can use another callback to retrieve the value as a dictionary and do something with it.
You could use it by setting a variable when the second callback is triggered or you could use State("color-store", "data") in other callbacks.

display datatable after filtering rows from dropdown list in dash

I'm new to Dash. I would like to make a app, where I can select values from dropdown filter, filter dataset and display the data table. I'm using dash_table.
My example app code is below. No datatable is shown. Does anyone know what I did wrong? How can I render dash table in dash app?
import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_table as dt
from dash.dependencies import Input, Output
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
app = dash.Dash(__name__)
states = df.State.unique().tolist()
app.layout = html.Div(
children=[
dcc.Dropdown(
id='filter_dropdown',
options=[{'label':st, 'value':st} for st in states],
value = states[0]
),
dt.DataTable(id='table-container') ]
)
#app.callback(
Output('table-container', 'data'),
[Input('filter_dropdown', 'value') ] )
def display_table(state):
dff = df[df.State==state]
return dff
if __name__ == '__main__':
app.run_server(debug=True)
BTW, do anyone know where I can find collections of dash app gallery with code?
You have to set the columns of your data table and return your dataframe as a dict in a special form. So change these two lines in your code to make it work.
dt.DataTable(id='table-container', columns=[{'id': c, 'name': c} for c in df.columns.values])
return dff.to_dict('records')
BTW, do anyone know where I can find collections of dash app gallery with code?
Best place with lots of examples with code is the Dash User Guide. You can for instance find the data table there.

Dash modal with multiple buttons that open it

Following this part of the docs: https://dash-bootstrap-components.opensource.faculty.ai/l/components/modal I've created a modal in my Dash app. The trigger for the modal will be dynamically rendered thumbnails. When any of them is clicked, the modal should open and display the image from the thumbnail as it's body.
Is is possible, inside Dash, to have multiple buttons (I don't know how many will there be, depending on how many thumbnails in the database) that will all open the same modal dialog and pass some of their data to the modal (such as img src in my case)?
The input in the example above is simple:
[
Input("open", "n_clicks"), Input("close", "n_clicks")
],
but in reality I don't know how many will there be and can't hardcode an ID.
Any suggestions?
Yes, you can have multiple buttons open a modal. Just as you showed, the callback would have an Input for each one. No, you cannot create them dynamically. Dash does not play well with any ID that is not in the layout at the start of running the app.
Create a set of buttons dynamically using the below list comprehension:
[dcc.Button(x, id={'type': 'thumbnail_button', 'index': x}) for x in thumbnail_list]
Use the pattern-matching callback to open modal when any of these buttons are clicked:
#app.callback(
Output('your-modal', 'is_open'),
[Input({'type': 'thumbnail_button', 'index': ALL}, 'n_clicks')]
)
def handle_button_click(n_clicks):
invoker = [p['prop id'] for p in dash.callback_context.triggered][0]
invoker_type = json.loads(invoker.split('.')[0])['type']
invoker_index = json.loads(invoker.split('.')[0])['index']
if invoker_type == "thumbnail_button":
return not is_open
else:
return is_open
Lastly the imports:
from dash.dependencies import Input, Output, ALL

Plotly Dash tabs and interactive graphs

In my dash I have a set of tabs with a graph inside. Each tab has one graph. I have a 'clickdata' callback that runs a function every time you click on one of the graphs, and it works so far I don't change the tab. But once I change the tab the 'clickdata' callback to the graphs stop working. Any idea?
In case it help, this is the structure of my code:
app = dash.Dash(__name__)
app.layout = html.Div([
... #deleted code
html.Button(id='Calculate_button',
n_clicks=0,
children='Calculate',
style={'fontSize':18,
'width':'100%'}),
html.Div([
dcc.Tabs(id="tabs",
value='tab-1',
children=[dcc.Tab([dcc.Graph(id='LapLabels',
style={'height':1000,
'paddingTop':30})],
label='Lap Labels',
value='tab-1',
id='tab-1'),
dcc.Tab([dcc.Graph(id='RacePlot',
style={'height':1000,
'paddingTop':30})],
label='Raceplot',
value='tab-2',
id='tab-2'),])])])
#app.callback(Output('LapLabels','figure'),
[Input('Calculate_button','n_clicks')],
[State('input1','value'),
State('input2','value'),
State('csvcontainer','value')])
def update_Labels(n_clicks,Traffic_Trigger,Slow_Percent2best,path):
return LapLabels(Traffic_Trigger,Slow_Percent2best,path) #this function returns a figure
#app.callback(Output('Calculate_button','n_clicks'),
[Input('LapLabels','clickData'),
Input('RacePlot','clickData')],
[State('csvcontainer','value')])
def modsc_Labels(hoverData,hoverDataRplot,path):
return myfunc(hoverData,hoverDataRplot,path) #this function updates the file that LapLabels reads

Categories