I am looking to add a scroll bar to a side bar panel for a Dash application - see this app as an example. I can get the scroll bar to show up dynamically when content runs off the page, but the only way I can seem to get the main page div to show up to the right of the sidebar div is to set the CSS style "position": "fixed". However, that setting keeps the content fixed in place even when a scroll bar is available.
Here is the code:
import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
# the style arguments for the sidebar. We use position:fixed and a fixed width
SIDEBAR_STYLE = {
"position": "fixed",
"top": 0,
"left": 0,
"bottom": 0,
"width": "16rem",
"padding": "2rem 1rem",
"background-color": "#f8f9fa",
}
# the styles for the main content position it to the right of the sidebar and
# add some padding.
CONTENT_STYLE = {
"margin-left": "18rem",
"margin-right": "2rem",
"padding": "2rem 1rem",
"display": "inline-block"
}
sidebar = html.Div(
[
html.H2("Sidebar", className="display-4"),
html.Hr(),
html.P(
"A simple sidebar", className="lead"
),
],
style=SIDEBAR_STYLE,
)
maindiv = html.Div(
id="first-div",
children=[
# first row
html.Div([
html.H2("First Row"),
html.Hr(),
html.P(
"First row stuff", className="lead"
)
]),
# second row
html.Div([
html.H2("Second Row"),
html.Hr(),
html.P(
"Second row stuff", className="lead"
)
])
],
style=CONTENT_STYLE
)
app.layout = html.Div([sidebar, maindiv])
if __name__ == "__main__":
app.run_server(port=8888)
Okay.. it was as simple as adding "overflow": "scroll" in my SIDEBAR_STYLE dict.
Related
I am working on a multipage app and registered all the pages correctly (script 1 below).
I would now like to add a button on each page which goes to an Explanatory page, so this button should be excluded from the CSS inline-block styling. I just cant get the HREF of this page specific button to redirect to the correct page content. It does change to the /name but shows 404 not found content...
THIS IS THE SCRIPT OF THE MAIN PAGE MULTIPAGE APP
import dash
import os
app = Dash(__name__, use_pages=True)
app.layout = html.Div([
html.Img(src=r'EXAMPLE_LINK.png',
style={'height': '100px', 'width': '450px'}),
html.H3('TITLE OF THE DASHBOARD',
style={'color': '#005aa0', 'font-size': '20px', 'font-family': 'sans-serif'}),
html.Div(
[
html.Div(
dcc.Link(
html.Button(children=page['name'][:][7:8].upper() + page['name'][:][8:].lower(),
style={"width": "200px", "height": "40px", "marginLeft": "5%", "color": "#005aa0",
'border': '1.5px black solid', 'font-size': '15px'}), href=page["relative_path"]),
style={"display": "inline-block",
"width": "10%",
"margin-left": "12%",
"verticalAlign": "top"}
)
for page in dash.page_registry.values()
],
),
html.H1(children=LOGGED IN AS {os.getlogin()}',
style={'color': '#005aa0', 'font-size': '15px', 'font-family': 'sans-serif'}),
dash.page_container
])
if __name__ == '__main__':
app.run_server(debug=True)
AND THIS IS THE BUTTON WHICH I WANT TO IMPEMENT ON THE PAGES
html.Div([
dcc.Link(html.Button(children='?', id='p1_roll1', n_clicks=1,
style={"width": "150px", "height": "60px", "marginLeft": "0%",
"background-color": "#ffffff", 'color': '005aa0',
'font-size': '40px', "display": "inline-block"}), href='ExplanationPage.py'),
html.H1(children='TITLE EXAMPLE',
style={'text-align': 'center', 'color': '#005aa0', 'font-size': '60px', 'marginLeft': '33%',
'font-family': 'sans-serif', "display": "inline-block"})
]),
So my question is: How can i redirect the HREF= (in the pages link button: href='ExplanationPage.py') to a python script which shouldnt be among the ones registered in the page['name'] inblock styling.
I want to trigger an event if the checkbox of a dash-table is clicked. When I start the webapp, I see below output
* Serving Flask app 'app'
* Debug mode: on
aaaa
[]
aaaa
[]
where "aaaa" indicating the callback is triggered. But when I click the checkbox after the initial load, nothing happens. I would expect that if I click the checkbox of a table, the callback-function dummy was triggered. Why is it not triggered?
import dash
import dash_bootstrap_components as dbc
from dash import html
from dash import dcc, dash_table
import plotly.express as px
from dash.dependencies import Input, Output
import pandas as pd
# data source: https://www.kaggle.com/chubak/iranian-students-from-1968-to-2017
# data owner: Chubak Bidpaa
df = pd.read_csv('https://raw.githubusercontent.com/Coding-with-Adam/Dash-by-Plotly/master/Bootstrap/Side-Bar/iranian_students.csv')
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
# styling the sidebar
SIDEBAR_STYLE = {
"position": "fixed",
"top": 0,
"left": 0,
"bottom": 0,
"width": "16rem",
"padding": "2rem 1rem",
"background-color": "#f8f9fa",
}
# padding for the page content
CONTENT_STYLE = {
"margin-left": "18rem",
"margin-right": "2rem",
"padding": "2rem 1rem",
}
sidebar = html.Div(
[
html.H2("", className="display-4"),
html.Hr(),
html.H2("Sidebar", className="display-4"),
html.Hr(),
html.P(
"Number of students per education level", className="lead"
),
dbc.Nav(
[
dbc.NavLink("Home", href="/", active="exact"),
dbc.NavLink("Page 1", href="/page-1", active="exact"),
dbc.NavLink("Page 2", href="/page-2", active="exact"),
],
vertical=True,
pills=True,
),
],
style=SIDEBAR_STYLE,
)
navbar = dbc.NavbarSimple(
children=[
dbc.NavItem(dbc.NavLink("Page 1", href="#")),
dbc.DropdownMenu(
children=[
dbc.DropdownMenuItem("More pages", header=True),
dbc.DropdownMenuItem("Page 2", href="#"),
dbc.DropdownMenuItem("Page 3", href="#"),
],
nav=True,
in_navbar=True,
label="More",
),
],
brand="NavbarSimple",
brand_href="#",
color="primary",
dark=True,
)
fig1 = px.bar(df, barmode='group', x='Years',
y=['Girls Kindergarten', 'Boys Kindergarten'])
fig1.update_layout(plot_bgcolor='rgb(10,10,10)')
children1 = [html.H1('Kindergarten in Iran',
style={'textAlign':'center'}),
dcc.Graph(id='bargraph',
figure=fig1),
dash_table.DataTable(
id='datatable-interactivity',
columns=[
{"name": i, "id": i, "deletable": True, "selectable": True} for i in df.columns
],
data=df.to_dict('records'),
editable=True,
filter_action="native",
sort_action="native",
sort_mode="multi",
column_selectable="single",
row_selectable="multi",
row_deletable=True,
selected_columns=[],
selected_rows=[],
page_action="native",
page_current= 0,
page_size= 10,
)]
content = html.Div(id="page-content", children=children1, style=CONTENT_STYLE)
app.layout = html.Div([
dcc.Location(id="url"),
sidebar,
navbar,
content
])
#fig1.update_layout(plot_bgcolor='rgb(10,10,10)')
"""
def update_styles(selected_columns):
return [{
'if': { 'column_id': i },
'background_color': '#D2F3FF'
} for i in selected_columns]
"""
#app.callback(
Output('datatable-interactivity', 'style_data_conditional'),
Input('datatable-interactivity', 'selected_columns')
)
def dummy(selected_columns):
print("aaaa")
print(selected_columns)
#app.callback(
Output("page-content", "children"),
[Input("url", "pathname")]
)
def render_page_content(pathname):
if pathname == "/":
return children1
elif pathname == "/page-1":
return children1
elif pathname == "/page-2":
return children1
# If the user tries to reach a different page, return a 404 message
return dbc.Jumbotron(
[
html.H1("404: Not found", className="text-danger"),
html.Hr(),
html.P(f"The pathname {pathname} was not recognised..."),
]
)
if __name__=='__main__':
app.run_server(debug=True)
The dummy function accepts a wrong input parameter. I have not worked with selected_columns, but selected_rows so far. A function input needed to be "chosen_rows" then for the selected_rows.
I have a radio element and a text box element in my dash application. I'd like to update the text the field based on the selected option from a callback.
dbc.InputGroup(
[
dbc.RadioItems(
id="type",
persistence=True,
persistence_type="memory",
options=[
{"label": "option1", "value": "option1"},
{"label": "option2", "value": "option2"}
],
value="option1",
style={"margin-left":"8px"}
),
],
style={"margin-top":"20px","width": "80%", "float": "left"},
),
dbc.InputGroup(
[
dbc.InputGroupAddon("Floor", style={"margin-left":"8px"}),
dbc.Input(
id="floor",
persistence=True,
persistence_type="memory"
),
],
),
How do I make the text "Floor" to be dynamic based on the option selected in the radio?
You need to use the #app.callback in order to make your InputGroupAddon dynamic
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
app = dash.Dash(__name__)
app.layout = (
html.Div([
dbc.InputGroup([
dbc.RadioItems(
id="type",
persistence=True,
persistence_type="memory",
options=[
{"label": "option1", "value": "option1"},
{"label": "option2", "value": "option2"}
],
value="option1",
style={"margin-left":"8px"}
),
],
style={"margin-top":"20px","width": "80%", "float": "left"},
),
dbc.InputGroup([
dbc.InputGroupAddon(
id='dbc-input-addon',
style={"margin-left":"8px"}),
dbc.Input(
id="floor",
persistence=True,
persistence_type="memory"
),
])
])
)
#app.callback(
Output(component_id='dbc-input-addon', component_property='children'),
[Input(component_id='type', component_property='value')]
)
def change_input(option_value):
if option_value == 'option1':
input_txt = 'Floor'
elif option_value == 'option2':
input_txt = 'No floor'
return input_txt
if __name__ == '__main__':
app.run_server(debug=True)
I am new to Plotly Dash and trying to develop a multi-page App. How can I use both Sidebar and Navbar simultaneously?
I have below an example code where the Sidebar is coming above Navbar. I have tried searching similar examples but couldn't find any.
Any help would be awesome. Thanks.
import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
# link fontawesome to get the chevron icons
FA = "https://use.fontawesome.com/releases/v5.8.1/css/all.css"
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP, FA])
# the style arguments for the sidebar. We use position:fixed and a fixed width
SIDEBAR_STYLE = {
"position": "fixed",
"top": 0,
"left": 0,
"bottom": 0,
"width": "16rem",
"padding": "2rem 1rem",
"background-color": "#f8f9fa",
}
# the styles for the main content position it to the right of the sidebar and
# add some padding.
CONTENT_STYLE = {
"margin-left": "18rem",
"margin-right": "2rem",
"padding": "2rem 1rem",
}
submenu_1 = [
html.Li(
# use Row and Col components to position the chevrons
dbc.Row(
[
dbc.Col("Menu 1"),
dbc.Col(
html.I(className="fas fa-chevron-right mr-3"), width="auto"
),
],
className="my-1",
),
id="submenu-1",
),
# we use the Collapse component to hide and reveal the navigation links
dbc.Collapse(
[
dbc.NavLink("Page 1.1", href="/page-1/1"),
dbc.NavLink("Page 1.2", href="/page-1/2"),
],
id="submenu-1-collapse",
),
]
submenu_2 = [
html.Li(
dbc.Row(
[
dbc.Col("Menu 2"),
dbc.Col(
html.I(className="fas fa-chevron-right mr-3"), width="auto"
),
],
className="my-1",
),
id="submenu-2",
),
dbc.Collapse(
[
dbc.NavLink("Page 2.1", href="/page-2/1"),
dbc.NavLink("Page 2.2", href="/page-2/2"),
],
id="submenu-2-collapse",
),
]
sidebar = html.Div(
[
html.H2("Sidebar", className="display-5"),
html.Hr(),
html.P(
"A sidebar with collapsible navigation links", className="lead"
),
dbc.Nav(submenu_1 + submenu_2, vertical=True),
],
style=SIDEBAR_STYLE,
id="sidebar",
)
PLOTLY_LOGO = "https://images.plot.ly/logo/new-branding/plotly-logomark.png"
search_bar = dbc.Row(
[
dbc.Col(dbc.Input(type="search", placeholder="Search")),
dbc.Col(
dbc.Button("Search", color="primary", className="ml-2"),
width="auto",
),
],
no_gutters=True,
className="ml-auto flex-nowrap mt-3 mt-md-0",
align="center",
)
navbar = dbc.Navbar(
[
html.A(
# Use row and col to control vertical alignment of logo / brand
dbc.Row(
[
dbc.Col(html.Img(src=PLOTLY_LOGO, height="30px")),
dbc.Col(dbc.NavbarBrand("Navbar", className="ml-2")),
],
align="center",
no_gutters=True,
),
href="https://plot.ly",
),
dbc.NavbarToggler(id="navbar-toggler"),
dbc.Collapse(search_bar, id="navbar-collapse", navbar=True),
],
color="dark",
dark=True,
)
content = html.Div(id="page-content", style=CONTENT_STYLE)
app.layout = html.Div([dcc.Location(id="url"), navbar,sidebar, content])
# this function is used to toggle the is_open property of each Collapse
def toggle_collapse(n, is_open):
if n:
return not is_open
return is_open
# this function applies the "open" class to rotate the chevron
def set_navitem_class(is_open):
if is_open:
return "open"
return ""
for i in [1, 2]:
app.callback(
Output(f"submenu-{i}-collapse", "is_open"),
[Input(f"submenu-{i}", "n_clicks")],
[State(f"submenu-{i}-collapse", "is_open")],
)(toggle_collapse)
app.callback(
Output(f"submenu-{i}", "className"),
[Input(f"submenu-{i}-collapse", "is_open")],
)(set_navitem_class)
#app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def render_page_content(pathname):
if pathname in ["/", "/page-1/1"]:
return html.P("This is the content of page 1.1!")
elif pathname == "/page-1/2":
return html.P("This is the content of page 1.2. Yay!")
elif pathname == "/page-2/1":
return html.P("Oh cool, this is page 2.1!")
elif pathname == "/page-2/2":
return html.P("No way! This is page 2.2!")
# If the user tries to reach a different page, return a 404 message
return dbc.Jumbotron(
[
html.H1("404: Not found", className="text-danger"),
html.Hr(),
html.P(f"The pathname {pathname} was not recognised..."),
]
)
# add callback for toggling the collapse on small screens
#app.callback(
Output("navbar-collapse", "is_open"),
[Input("navbar-toggler", "n_clicks")],
[State("navbar-collapse", "is_open")],
)
def toggle_navbar_collapse(n, is_open):
if n:
return not is_open
return is_open
if __name__ == "__main__":
app.run_server(port=8888, debug=True)
This same issue was reported in the dash-bootstrap-components GitHub repo: https://github.com/facultyai/dash-bootstrap-components/issues/321. The recommendation was to adjust the sidebar padding:
SIDEBAR_STYLE = {
...,
"padding": "4rem 1rem 2rem",
...,
}
I'm trying to 'Pythonify' card generation in a function, but it seems to not be popping up. Perhaps I'm doing something wrong, or perhaps the dashboard I'm building needs to be quite vertical. Basically, the cardify function doesn't generate a card.
Thanks for the help in advance!
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
app = dash.Dash(external_stylesheets=[dbc.themes.MINTY])
def cardify(metricname, metricvalue, recapstring):
dbc.Card(
[
dbc.CardBody(
[
html.H2(metricname, className="card-title"),
html.H4(metricvalue, className="card-title"),
html.P(
recapstring,
className="card-text",
),
]
),
],
# style={"width": "18rem"},
)
app.layout = \
html.Div(
[
dbc.Row(
[
dbc.Col(
cardify("Card Title", "Metric Value", "Some Quick Example yada yada"),
width={"size": 2, "order": 1, "offset": 1},
),
dbc.Col(
dbc.Card(
[
dbc.CardBody(
[
html.H4("Card title", className="card-title"),
html.P(
"Some quick example text to build on the card title and "
"make up the bulk of the card's content.",
className="card-text",
),
]
),
],
# style={"width": "18rem"},
),
width={"size": 2, "order": 2},
)
]
),
]
)
if __name__ == "__main__":
app.run_server(debug=True)
Your function cardify needs to return dbc.Card.