How to add dbc.Tabs to Dash: Multi-Page App with Pages? - python

I'm using tabs inside of Plotly Dash application like given below, and it works fine.
import dash
from dash import Dash, dash_table, dcc, html, Input, Output, callback, State
import plotly.express as px
import dash_bootstrap_components as dbc
import pandas as pd
import plotly.graph_objs as go
import plotly.express as px
tabs = html.Div(
[
dbc.Tabs(
[
dbc.Tab(label="Tab 1", tab_id="tab-1"),
dbc.Tab(label="Tab 2", tab_id="tab-2"),
],
id="tabs",
active_tab="tab-1",
),
html.Div(id="content"),
]
)
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.title = "Financial Report"
server = app.server
app.layout = html.Div(
dbc.Row([
tabs])
)
#app.callback(Output("content", "children"), [Input("tabs", "active_tab")])
def ind2(value):
purchase = {'date': ['11/03/2021', '12/03/2021', '14/03/2021', '11/03/2021'],
'price': [300, 400, 200, 200],
'currency': ['eur', 'usd', 'usd', 'usd'],
'qty': [200, 300, 400, 500],
'salesman': ['AC', 'BC', "CC", 'DC']}
pur = pd.DataFrame(purchase)
fig2 = go.Figure()
for i in pur['currency'].unique():
fig2.add_trace(go.Bar(x=pur['date'], y=pur[pur['currency'] == i]['qty'], name=i))
fig2.update_layout(barmode="group")
if value=='tab-2':
return dbc.Row(
[
dbc.Col(dcc.Graph(id='bargraph',
figure=fig2)),
]
)
else:
return html.P("Welcome...")
if __name__ == "__main__":
app.run_server(debug=True)
But when I'm trying to add this code to the Dash Page which has mutlti pages it doesn't return anything, tabs seem to be inactive.
(https://dash.plotly.com/urls#example-with-different-pages)
to summarize, I want this page as in picture below. but not only side bar working but tabs inside of the page also.

oh, I figured it out, that main problem was #app.callback.
Since we don't have app in the multipage application (I mean in each page, so just #callback should be used).

Related

There is a Horizontal Scrollbar dasboard plotly

I am building a dashboard with multi-Page Apps plotly and bootstrap. There is a horizontal scrollbar overflow on my website. I am looking to remove a scroll bar, and remove this blank space after imagen, thank you.
Here is the code:
App:
import pandas as pd
from dash_auth import BasicAuth
from dash import Dash, dcc, html, Input, Output, callback
from dash_extensions.enrich import ServersideOutput, DashProxy, ServersideOutputTransform
import dash_bootstrap_components as dbc
from pages import test, error_404
df = pd.read_parquet('dataset.parquet.gzip')
external_stylesheets = [
dbc.themes.BOOTSTRAP,
dbc.icons.BOOTSTRAP,
]
app = Dash(__name__, title = 'Test',
external_stylesheets=external_stylesheets,
suppress_callback_exceptions=True,
)
server = app.server
app.layout = html.Div([
dcc.Location(id="url", pathname="", refresh=False),
# Header
dbc.Row([
dbc.Col(html.A(
html.Img(src=app.get_asset_url("leters.jpg"), className="img-fluid brand-other"),
id="logo",
href="https://www.leters.com/", target="blank"
), width='12', class_name='justify-content-end d-flex'),
]),
html.Div(id='page-content'),
], className='col-12 col-lg-12')
#callback(
Output(component_id='page-content', component_property='children'),
Input(component_id='url', component_property='pathname')
)
def routing(path):
print(path)
if path == "":
return test.test
else:
return error_404
if __name__ == "__main__":
app.run_server(debug=True)
test:
from dash import html
test = html.Div([
html.H3("test", className="sub_title"),
])
I think you should change from html.Div to dbc.Container as below:
app.layout = dbc.Container([
dcc.Location(id="url", pathname="", refresh=False),
# Header
dbc.Row([
dbc.Col(html.A(
html.Img(src=app.get_asset_url("leters.jpg"), className="img-fluid brand-other"),
id="logo",
href="https://www.leters.com/", target="blank"
), width='12', class_name='justify-content-end d-flex'),
]),
html.Div(id='page-content'),
], fluid=True)
Hope this help.

Dropdown menu isn't searchable with images as labels

Adding images to dropdown labels as described in paragraph Components as Option Labels in
https://dash.plotly.com/dash-core-components/dropdown
makes labels not searchable even though searchable=True is set.
Is there workaround to make labels searchable as usual?
Minimal working code:
import pandas as pd
import plotly
import plotly.express as px
import json
import dash_bootstrap_components as dbc
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
df = pd.read_csv('data_bdo.csv', index_col=0)
temp=[
{
"label": html.Div(
[
html.Img(src="/assets/1.png", height=20),
html.Div("Python", style={'font-size': 15, 'padding-left': 10}),
], style={'display': 'flex', 'align-items': 'center', 'justify-content': 'center'}
),
"value": "Python",
},
{
"label": html.Div(
[
html.Img(src="/assets/2.png", height=20),
html.Div("Julia", style={'font-size': 15, 'padding-left': 10}),
], style={'display': 'flex', 'align-items': 'center', 'justify-content': 'center'}
),
"value": "Julia",
},]
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.DARKLY],update_title = None )
app.layout = html.Div([
html.Div([
dcc.Dropdown(id='my_dropdown',
options=temp,
searchable=True #allow user-searching of dropdown values
)],className='three columns')])
#app.callback(
Output(component_id='the_graph', component_property='figure'),
[Input(component_id='my_dropdown', component_property='value')]
)
def update_bar_chart(my_dropdown):
df = pd.read_csv('data_bdo.csv', index_col=0)
fig = px.bar(df[["name", my_dropdown]].dropna().sort_values(by=my_dropdown,ascending=False),
x="name",
y=my_dropdown,
template = 'plotly_dark',
text=my_dropdown,
labels={my_dropdown:"Amount of "+ str(my_dropdown)}
)
fig.update_traces(textfont_size=13, textposition="outside", cliponaxis=False)
return fig
if __name__ == '__main__':
app.run_server(debug=True, use_reloader=False)
Dropdown with options of the form [{'label': 'Python', 'value': 'Python'}] is searchable though...

Updating dbc.Card with hoverData

I have the following skeleton code
# ------------------------------
# IMPORT LIBRARIES
# ------------------------------
# Import Dash and Dash Bootstrap Components
import dash
import dash_bootstrap_components as dbc
from dash import Input, Output, dcc, html, dash_table, State
import dash_leaflet as dl
# Import Core Libraries
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from dash import Input, Output, dcc, html, dash_table
token='my_token'
FONT_AWESOME = "https://use.fontawesome.com/releases/v5.10.2/css/all.css"
# Import data
data_url = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vSGcAFoXyMXk7lj3KJrpzKd5XiBufm2xa7M39QNZxw5ma0TZhP35q-mf2ybyf9cZQdEwsoWkHiQWfjC/pub?gid=0&single=true&output=csv'
df = pd.read_csv(data_url)
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP,FONT_AWESOME], title='CONFIRM - SK4U', update_title=None,
meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=0.7, minimum-scale=0.4"}],
)
server = app.server
fig_map = px.scatter_mapbox(df,lat='latitude',lon='longitude',
mapbox_style='mapbox://styles/vostpt/cl1w0k6uf000415nt86nk7uv2',
#color='Kategória / Category',
width=1400,height=700,
hover_name='name',
#center=[48.799330977271445,19.338585158029197],
center=dict(lon=20.0068, lat=48.8264),
zoom=7,
custom_data=['name']
)
fig_map.update_layout(
hoverlabel=dict(
bgcolor="white",
font_size=16,
font_family="sans-serif"
)
)
fig_map.update_layout(mapbox = dict(accesstoken = token, style ='mapbox://styles/vostpt/cl1w0k6uf000415nt86nk7uv2'))
app.layout = html.Div(
[
dbc.Row(
[
dbc.Col(
dbc.Card(
dbc.CardBody(
[
html.H4("Title", className="card-title"),
html.H6("Card subtitle", className="card-subtitle"),
html.P(id="card_data"),
dbc.CardLink("Card link", href="#"),
dbc.CardLink("External link", href="https://google.com"),
]
),
),
),
dbc.Col(
dcc.Graph(id="my_map",figure=fig_map),
xs=12,
),
],
),
],
)
#app.callback(
Output(component_id="card_data", component_property="children"),
Input(component_id="my_map", component_property="hoverData")
)
def upgrade_card(hoverData):
title = hoverData['name'][0]
return title
if __name__ == "__main__":
app.run_server(host='0.0.0.0', debug=True)
My objective is to update the text in the card, with the data from the dataframe, on mouse hover.
The app receives the input from the hoverData but returns the error message
TypeError: 'NoneType' object is not subscriptable
Any help would be much appreciated.
Disclaimer: The solution will be used in a non-for-profit NGO's project. No commercial use will be made of the solution
These errors usually come up when you did not properly initialize. The children of the p-tag are non-existent in your example, so they cannot be updated.
So, replace html.P(id="card_data") with html.P("", id="card_data").

Plotly: How to create 'input text' on one page and output (graphs) on second page or tab, by using plotly-dash?

I am creating an app where the first page should take only 'text input' and results(graph) must show on second page or new tab. I do not want text input and charts on the same page. It means, if I write the input as 'USA' in text input bar, the graph of USA should populate on second tab. Following is the working code that I have written so far in dropdown format. In this code, dropdown and graphs are on the same page which I do not want. Please suggest.
import pandas as pd
import plotly.express as px
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Output, Input
import numpy as np
import plotly.io as pio
pio.renderers.default='browser'
app = dash.Dash(__name__)
app.layout = html.Div([
html.H1("Economy Analysis"),
dcc.Dropdown(id='Country_select',
options=[{'label': x, 'value': x}
for x in df.Country.unique()],
value = 'USA'
),
dcc.Graph(id ='my-graph', figure = {})
])
#app.callback(
Output(component_id = 'my-graph', component_property = 'figure'),
Input(component_id = 'Country_select', component_property = 'value'))
def interactive_graphing(value_country):
print(value_country)
s = 100
cat_g = ["developing","develop"]
sample_cat = [cat_g[np.random.randint(0,2)]for i in range(100)]
df = pd.DataFrame({"Country": np.random.choice(["USA", "JPY", "MEX", "IND", "AUS"], s),
"Net": np.random.randint(5, 75, s),
})
df["sample_cat"] = sample_cat
df = df[df.Country==value_country]
df2 = df.pivot_table(index='Country',columns='sample_cat',values='Net',aggfunc='sum')
df2.reset_index(inplace=True)
fig = px.bar(df2, x="Country",
y=['develop','developing'])
return fig
if __name__=='__main__':
app.run_server()
You can use dcc.Tabs and dcc.Tab containers in your layout, and put the input/graph in separate tabs. Dash bootstrap components tabs would also work for this. The ids will still work as inputs/outputs with your callback.
Sample layout:
app.layout = html.Div([
html.H1("Economy Analysis"),
dcc.Tabs([
dcc.Tab(
label='Dropdown',
children=[
dcc.Dropdown(id='Country_select',
options=[{'label': x, 'value': x}
for x in df.Country.unique()],
value = 'USA')
]
),
dcc.Tab(
label='Graph',
children=[
dcc.Graph(id ='my-graph')
]
)
])
])

Plotly/Dash -- range filter resets on hoverData

I am trying capture mouse hover events using Dash. I capture the position of the mouse using hoverData.
The problem appears when I filter the time series using the range selector or the range slider. The plot correctly reduces to the selected time, but when I hover it with the mouse it resets to the main view (whole main series).
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv")
app.layout = html.Div([
dcc.Graph(
id='stock-plot'
),
], className="container")
#app.callback(
Output('stock-plot', 'figure'),
[Input('stock-plot', 'hoverData')])
def drawStockPrice(hoverData):
traces = [go.Scatter(
x=df.Date,
y=df['AAPL.High'],
mode='lines',
opacity=0.7,
connectgaps=True),
]
return {'data': traces,
'layout': go.Layout(colorway=["#5E0DAC", '#FF4F00', '#375CB1', '#FF7400', '#FFF400', '#FF0056'],
height=600,
title=f"Closing prices",
xaxis={"title": "Date",
'rangeselector': {'buttons': list([{'count': 1, 'label': '1M',
'step': 'month',
'stepmode': 'backward'},
{'count': 6, 'label': '6M',
'step': 'month',
'stepmode': 'backward'},
{'step': 'all'}])},
'rangeslider': {'visible': True}, 'type': 'date'},
yaxis={"title": "Price (USD)"},
)}
if __name__ == '__main__':
app.run_server(debug=True)
I am sure there should be a better solution but this is what I got (Dash v1.6.0):
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output, State
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv")
layout = go.Layout( colorway=["#5E0DAC", '#FF4F00', '#375CB1', '#FF7400', '#FFF400', '#FF0056'],
height=600,
title=f"Closing prices",
xaxis={"title": "Date",
'rangeselector': {'buttons': list([{'count': 1, 'label': '1M',
'step': 'month',
'stepmode': 'backward'},
{'count': 6, 'label': '6M',
'step': 'month',
'stepmode': 'backward'},
{'step': 'all'}]
),
},
'rangeslider': {'visible': True},
'type': 'date',
},
yaxis={"title": "Price (USD)"},
)
traces = [go.Scatter( x=df.Date,
y=df['AAPL.High'],
mode='lines',
opacity=0.7,
connectgaps=True
)]
app.layout = html.Div([
dcc.Graph(
id='stock-plot',
figure={
'data': traces,
'layout': layout
}
),
], className="container")
#app.callback(
Output('stock-plot', 'figure'),
[Input('stock-plot', 'hoverData'),
Input('stock-plot', 'relayoutData')],
[State('stock-plot', 'figure')]
)
def drawStockPrice(hoverData, selected, figure):
data = figure['data']
layout = figure['layout']
if selected is not None and 'xaxis.range' in selected:
layout['xaxis']['range'] = selected['xaxis.range']
return {'data': data,
'layout': layout
}
if __name__ == '__main__':
app.run_server(debug=True)

Categories

Resources