How to connect HTML elements with Dash Callback in Python - html

I'm using both html elements and dash bootstrap components in my code and wonder if I can connect an HTML component with a Dash component in callback. For example, I have a dash dropdown menu and want to update the html text based on the input of the dropdown menu.
#dropdown
html.Div =(
[
dcc.Dropdown(
id="dropdown",
options=[
{"label": "option1", "value": "option1"},
{"label": "option2", "value": "option2"},
],
multi=True,
)
]
)
# HTML Components
html.Div =(
[
html.H2("The selected option is")
html.P(id="text-holder", children =["text"])
]
)
#app.callback(
Output("text-holder", "children"),
Input("dropdown", "value)
)
def fill_text(value):
return value
Once a user selects a value from the dropdown menu, I want the selected value to appear on the text line created by html.P. For example, if "option1" is selected from the dropdown menu, the text that appears on the HTML part should be also "option1".
If I run the current script, I don't get any error message but the html part doesn't get updated at all. I think the callback is incorrect but am not sure how to fix it.

Using html.Div =( ... alters the value of html.Div. And it's really important to get the layout right.
Perhaps this is what you're looking for:
from dash import dcc, html, Dash, Output, Input
app = Dash(__name__)
app.layout = html.Div(
[
# dropdown
html.Div(
[
dcc.Dropdown(
id="dropdown",
options=[
{"label": f"option{idx}", "value": f"option{idx}"}
for idx in range(1, 5)
],
multi=True,
value="not specified",
)
]
),
# HTML Components
html.Div([html.H2("The selected option is"), html.P(id="text-holder")]),
]
)
#app.callback(Output("text-holder", "children"), Input("dropdown", "value"))
def fill_text(value):
return value
if __name__ == "__main__":
app.run_server()

Related

How can I have my dash app comment list all the previously inputted comments?

I am trying to create a comment section in my dash app where the comments submitted will be updated as new comments are submitted.I tried different ways but it wasn't working.. this is the current code I have now which is able to return the most recent comment submitted.
layout = html.Div([
html.H3(children='Write Comments'),
dcc.Textarea(
id='textarea',
value='',
style={'width': '100%', 'height': 200},
),
html.Button('Submit', id='button', n_clicks=0),
html.Div(id='comment-output', style={'whiteSpace': 'pre-line'})
])
# Submit comment through pushing the 'submit' button
#callback(
Output('comment-output', 'children'),
Input('button', 'n_clicks'),
State('textarea', 'value')
)
def update_output(n_clicks, value):
if n_clicks > 0:
return 'Submitted Comment: {}'.format(value)
You have to include the history with the callback and then add to it, otherwise it will just overwrite with the latest. I've tried this locally and it works:
#callback(
Output('comment-output', 'children'),
Input('button', 'n_clicks'),
[
State('textarea', 'value'),
State('comment-output', 'children'),
],
)
def update_output(n_clicks, value, children):
if n_clicks > 0:
return f'{children}\n Submitted Comment: {value}'
else:
return ''

adding a local html file into a Div in plotly/dash

I created a Dash app. On one tab I have a dropdown and a submit button. In a callback I generate an html file, saved locally, based on quantstats library (reports.html)
I am trying to producing this html within an html.Div but no success so far. All I managed to do is to print out an hyperlink to my local file but not the file itself.
Here is the layout part:
layout = html.Div([
dbc.Container([
dbc.Row([
dbc.Col(html.H1("Reports", className="text-center"), className="mb-5 mt-5")
]),
dbc.Row([
dbc.Col(dcc.Dropdown(id='reports_type',
options=[
{'label': 'YTD', 'value': 1},
{'label': 'ITD', 'value': 2},
],
value=1,
style={'display': 'block'},
)),
dbc.Col(html.Button('Run report', id='reports_submit')),
])
]),
html.Div(id='reports_holder')
])
Here is the callback:
#app.callback(
Output('reports_holder', 'children'),
[
Input('reports_submit', 'n_clicks')
],
[
State('reports_type', 'value')
],
prevent_initial_call=True
)
def produce_report(n_clicks, reports_type):
if n_clicks:
df = some dataframe
if reports_type == 1: #YTD
current_df = df[df.index.year == datetime.date.today().year]
my_pfo = pd.Series(current_df['Close'].values, name='Close', index=current_df.index)
qs.reports.html(my_pfo, "SPY", output='quantstats-tearsheet.html', title='YTD Tearsheet')
else: #ITD
my_pfo = pd.Series(df['Close'].values, name='Close', index=df.index)
qs.reports.html(my_pfo, "SPY", output='quantstats-tearsheet.html', title='ITD Tearsheet')
f = codecs.open('quantstats-tearsheet.html', 'r')
return f
Here is my latest try using the codecs library (this creates an error because the html documents cannot be JSON serializable). If I return f.read() instead then this is not html formated.
As said before I tried html.A instead of html.Div in my layout but this produces only an hyperlink (as expected with html.A). Should I use the property target with html.A but then how do I sepcify that the document should be opened in that same html.A? There must be a straightforward solution to this but I can't find it (most solutions involve opening a local html file into a new browser tab...)
Edit: here is an example of the html report generated via quantstats

Graph not showing

I have the following code
# -*- coding: utf-8 -*-
# # Two Pie Charts
import time
import dash
import dash_bootstrap_components as dbc
import plotly.express as px
import pandas as pd
from dash import Input, Output, dcc, html
# Data treatment
df = pd.read_csv('https://raw.githubusercontent.com/JorgeMiguelGomes/LEG2022_MediaMonitor/main/legislativas_2022_media_monitor_29jan2022/data_products/legislativas_2022_final_dataset_percentages.csv')
df_individuals = pd.read_csv('https://raw.githubusercontent.com/JorgeMiguelGomes/LEG2022_MediaMonitor/main/legislativas_2022_media_monitor_29jan2022/data_products/legislativas_2022_all_candidates_filtered.csv')
df_individuals = df_individuals.drop(columns=["Unnamed: 0"])
df_indivuduals = df_individuals.drop(columns=["Post Created Date"])
df_individuals_melt=pd.melt(df_individuals,id_vars=['candidato','Page Name'])
# Styling
pie_color_map = {
"Angry":"#EB9486",
"Love":"#CAE7B9"
}
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP],suppress_callback_exceptions=True,
meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}],
)
app.layout = dbc.Container(
[
# First Row
dbc.Row(
[
dbc.Col(html.Hr(style={'borderWidth': "2vh", "width": "100%", "borderColor": "#CAE7B9","opacity": "unset"}),width={'size':2}),
dbc.Col(html.Hr(style={'borderWidth': "2vh", "width": "100%", "borderColor": "#F3DE8A","opacity": "unset"}),width={'size':2}),
dbc.Col(html.Hr(style={'borderWidth': "2vh", "width": "100%", "borderColor": "#EB9486","opacity": "unset"}),width={'size':2}),
dbc.Col(html.Hr(style={'borderWidth': "2vh", "width": "100%", "borderColor": "#7E7F9A","opacity": "unset"}),width={'size':2}),
dbc.Col(html.Hr(style={'borderWidth': "2vh", "width": "100%", "borderColor": "#97A7B3","opacity": "unset"}),width={'size':2}),
],className="g-0",
), # end of first row
dbc.Tabs(
[
dbc.Tab(label="About", tab_id="method", label_style={"color": "#CAE7B9"},tab_style={'background-color': '#97A7B3'},active_label_style={"background-color":"#080808"}),
dbc.Tab(label="Metrics by Totals", tab_id="totals", label_style={"color": "#F3DE8A"},tab_style={'background-color': '#7E7F9A'}, active_label_style={"background-color":"#080808"}),
dbc.Tab(label="Stacked Analysis", tab_id="stacked", label_style={"color": "#EB9486"},tab_style={'background-color': '#F3DE8A'}, active_label_style={"background-color":"#080808"}),
dbc.Tab(label="Love vs Angry", tab_id="love_angry", label_style={"color": "#7E7F9A"},tab_style={'background-color': '#EB9486'}, active_label_style={"background-color":"#080808"}),
dbc.Tab(label="Conclusions", tab_id="conclusions", label_style={"color": "#97A7B3"},tab_style={'background-color': '#F3DE8A'}, active_label_style={"background-color":"#080808"}),
],
id="tabs",
active_tab="love_angry", # this is the tab that will be active when the user comes to the website
), # end of tabs
html.Div(id="tab-content", className="p-5"),
]
)
# Callbacks
# Pie Chart for Candidates
# #app.callback(
# Output(component_id='graph_individuals', component_property='figure'),
# [Input(component_id='dropdown_candidates', component_property='value')],
# )
# def build_graph_individuals(column_chosen):
# dff = df
# totals_sentiment = dff.groupby(['candidato'])[['Love','Angry']].sum().reset_index()
# totals_sentiment_melt = pd.melt(totals_sentiment,id_vars="candidato")
# totals_sentiment_melt = totals_sentiment_melt[totals_sentiment_melt['candidato'] == column_chosen]
# fig_individuals = px.pie(totals_sentiment_melt,names="variable",values="value",hole=0.5, color="variable",color_discrete_map=pie_color_map)
# candidato_filter = column_chosen
# return fig_individuals
# Pie Chart for Media Outlets
#app.callback(
Output(component_id='graph_shares_comments', component_property='figure'),
Output(component_id='graph_individuals', component_property='figure'),
Input(component_id='dropdown_media_outlet', component_property='value'),
Input(component_id='dropdown_candidates', component_property='value')
)
def build_graphs(column_chosen, candidato_filter):
# Data Treatment for candidate graph
dff = df
totals_sentiment = dff.groupby(['candidato'])[['Love','Angry']].sum().reset_index()
totals_sentiment_melt = pd.melt(totals_sentiment,id_vars="candidato")
totals_sentiment_melt = totals_sentiment_melt[totals_sentiment_melt['candidato'] == column_chosen]
# Data Treatment for media graph
dff_m = df[df['candidato']== candidato_filter]
print(dff_m)
totals_sentiment_media = dff_m.groupby(['Page Name'])[['Love','Angry']].sum().reset_index()
totals_sentiment_media_melt = pd.melt(totals_sentiment_media,id_vars="Page Name")
totals_sentiment_media_melt = totals_sentiment_media_melt[totals_sentiment_media_melt['Page Name'] == column_chosen]
print("HELLO HELLO")
print(totals_sentiment_media_melt)
# Pice Charts
fig_candidates = px.pie(totals_sentiment_melt,names="variable",values="value",hole=0.5, color="variable",color_discrete_map=pie_color_map)
fig_media = px.pie(totals_sentiment_media_melt,names="variable",values="value",hole=0.6, color="variable",color_discrete_map=pie_color_map)
return fig_candidates, fig_media
# TABS CALLBACKS -------------------------------------
#app.callback(Output("tab-content", "children"),
[Input("tabs", "active_tab")])
def switch_tab(at):
if at == "love_angry":
tab4_content = dbc.Row(
[
dbc.Col(
[
dcc.Dropdown(
id='dropdown_candidates',
options=[{'label': i, 'value': i} for i in df_individuals_melt.candidato.unique()
],
optionHeight=35, #height/space between dropdown options
value='António Costa', #dropdown value selected automatically when page loads
disabled=False, #disable dropdown value selection
multi=False, #allow multiple dropdown values to be selected
searchable=True, #allow user-searching of dropdown values
search_value='', #remembers the value searched in dropdown
placeholder='Please select...', #gray, default text shown when no option is selected
clearable=True, #allow user to removes the selected value
style={'width':"100%"}, #use dictionary to define CSS styles of your dropdown
# className='select_box', #activate separate CSS document in assets folder
# persistence=True, #remembers dropdown value. Used with persistence_type
# persistence_type='memory' #remembers dropdown value selected until...
),
dbc.Col(
dcc.Graph(id='graph_individuals'),
),
],width={'size':6, 'offset':0}
),
dbc.Col(
[
dcc.Dropdown(
id='dropdown_media_outlet',
options=[{'label': i, 'value': i} for i in df['Page Name'].unique()
],
optionHeight=35, #height/space between dropdown options
value='Agência Lusa', #dropdown value selected automatically when page loads
disabled=False, #disable dropdown value selection
multi=False, #allow multiple dropdown values to be selected
searchable=True, #allow user-searching of dropdown values
search_value='', #remembers the value searched in dropdown
placeholder='Please select...', #gray, default text shown when no option is selected
clearable=True, #allow user to removes the selected value
style={'width':"100%"}, #use dictionary to define CSS styles of your dropdown
# className='select_box', #activate separate CSS document in assets folder
# persistence=True, #remembers dropdown value. Used with persistence_type
# persistence_type='memory' #remembers dropdown value selected until...
),
dbc.Col(
dcc.Graph(id='graph_shares_comments'),
),
],width={'size':6, 'offset':0}
),
],
),
return tab4_content
# Error Message
return html.P("FOR SUPPORT PURPOSES ONLY")
if __name__ == "__main__":
app.run_server(debug=True, port=8888)
The code is running without errors but as you can see in the image below, the chart on the left side is not rendering, and I'm totally lost.
I have inserted a print command in the script, and when I change the dropdowns the values change accordingly as they should.
However the pie chart remains empty, like it's not getting any information.
Maybe I've been looking at the same code for more hours than I should, and I'm missing something really simple, but I just can't spot it.
Any help would be really appreciated.
Disclosure This is not a commercial project nor will I use it in any commercial way.
You were filtering with the wrong keyword for totals_sentiment_melt, use this to correct it:
totals_sentiment_melt = totals_sentiment_melt[totals_sentiment_melt['candidato'] == candidato_filter]

dash_bootstrap_components Col and Row not showing as expected - just stacking each item

I am trying to build my first dash app and want to organize things using dbc.Col and dbc.Row. I'm trying to build something to look like this in the first tab section called "Equity Risk"...
basic layout i'm aiming for
Unfortunately, all that's returned on the first tab are 3 items vertically stacked on top of each other that each take up the full width of the screen.
This is my code so far - I'm not sure if this is enough code to diagnose the issue, but hopefully it is. I have double-checked the brackets/parenthesis, added width arguments to every column, and have googled similar things and still can't tell what's wrong. Any help would be much much appreciated!
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
auth = dash_auth.BasicAuth(app,USERNAME_PASSWORD_PAIRS)
server = app.server
# app layout
app.layout = html.Div([
# header banner with titles
html.Div(
children=[
html.H1('COMPANY NAME',
className="header-company-name"),
html.P('HISTORICAL EARNINGS SPREAD ANALYSIS', #'Historical earnings spread analysis',
className='header-page-name')
],
className="header-banner"
),
dcc.Tabs([
# THIS IS THE TAB THAT I'M TRYING TO ORGANIZE, BUT HAVE PROBLEMS WITH
dcc.Tab(label='Equity Risk', children=[
dbc.Container([
dbc.Row([
dbc.Col([
dbc.Row([
dbc.Col([
# user inputs and submit button
html.Div([
html.Div([
html.Div(children='User inputs',
className='block-title'),
html.Div(children='', className='title-line'),
html.Div(children='Enter a start and end date:',
className='input-title'),
dcc.DatePickerRange(id='my_date_range',
min_date_allowed=df.date.min(),
max_date_allowed=df.date.max(),
start_date=datetime(2007,1,1),
end_date=datetime.today()
)
],
),
html.Div(
children=[
html.Button(id='submit_button',
n_clicks=0,
children='Submit Inputs',
className='button')
],
)
],
# style={'width': '20%', 'display': 'inline-block', 'verticalAlign':'top'},
className='utilities-block'
)
], width=3)
]),
dbc.Row([
dbc.Col([
# checkbox
html.Div(
children=[
html.Div(children='Plot Adjustments',
className='block-title'),
html.Div(children='', className='title-line'),
dcc.RadioItems(id='plot_lines',
options=[
{'label':'Show mean and \u03C3 lines', 'value':'meanstd'},
{'label':'Show standard grid', 'value':'grid'}
],
value='meanstd',
labelStyle={'display':'block'},
inputClassName='radio-input',
labelClassName='radio-label')
],
# style={'width': '20%'},
className='utilities-block'
)
], width=3)
])
], width=3),
dbc.Col([
# graph
html.Div(
children=[
html.Div(children='Equity risk premium mainly between 15yr mean and -1\u03C3 in recent months',
className='block-title'),
html.Div(children='', className='title-line'),
dcc.Graph(id='my_graph',
figure=updated_figure,
style={'height': '83%'},
className='content-block')
],
# style={'width': '72%', 'display': 'inline-block', 'verticalAlign':'top', 'height':'450px'},
className='utilities-block'
)
], width=9)
]) # end of row
], fluid=True)
], style=tab_style, selected_style=tab_selected_style),
# IGNORE THIS TAB.. I HAVEN'T STARTED DOING ANY GRID LAYOUT YET
dcc.Tab(label='S&P vs P/E Ratio', children = [
html.Div(
children=[
html.Div(children='Spread between S&P price and P/E ratio is widening',
className='block-title'),
html.Div(children='', className='title-line'),
dcc.Graph(id='my_sp_pe_graph',
figure=sp_pe_figure,
style={'height': '90%'},
className='content-block')
],
style={'width': '75%', 'display': 'inline-block', 'verticalAlign': 'top', 'height': '550px',
'paddingLeft': '20px'},
className='utilities-block'
)
], style=tab_style, selected_style=tab_selected_style),
# dcc.Tab(label='Something Else', style=tab_style, selected_style=tab_selected_style)
], style=tabs_style)
])
The problem is caused by small width values for some Col elements. There is not enough horizontal space left to put elements next to each other which causes the elements to stack.
Basically what is happening is that the left part of the layout in the first tab has a column width of 3 and then the actual content is inside column elements which also have their width set to 3. If you inspect this part of the layout you will see that the width of this container is very small; the width is 1/16 of the row width.
So the solution is to either set the width of the inner most columns to 12 or to just use a regular div, since the outer column already only takes up 1/4 of the row width.

Mdl: Material Icon in input field

I am looking into a way to get the following (taken from the material website):
I have managed to do get an icon in an input field with Bootstrap using input-group. But I cannot find a good and clear way on how to do this with mdl.
I am using elm but a html/css solution is fine.
I solved it with some css stuff.
passwordIconStyle : Attribute Msg
passwordIconStyle =
style
[ ("position", "absolute")
, ("top", "18px")
, ("right", "5px")
, ("cursor", "pointer")
]
passwordField : Model -> Html Msg
passwordField model =
div [ style [ ("position", "relative") ] ]
[ Textfield.render Mdl [1] model.mdl
[ Textfield.label "Password"
, Textfield.floatingLabel
, Textfield.password
, Textfield.value model.password
, Textfield.error model.passwordError
|> Options.when (not <| isEmpty model.passwordError)
, Options.onInput UpdatePassword
, Options.css "padding-right" "40px"
]
[]
, i [ passwordIconStyle ]
[
visibility Color.gray 25
]
]
result:
I've done an this small example. I hope it can help you.
import Material as Mdl
import Material.Textfield as Textfield
import Html exposing (..)
type alias Model =
{ mdl :
Mdl.Model
}
model : Model
model =
{ mdl =
Mdl.model
-- Boilerplate: model store for any and all Mdl components you use.
}
type Msg
= Mdl (Mdl.Msg Msg)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
-- Boilerplate: Mdl action handler.
Mdl msg_ ->
Mdl.update Mdl msg_ model
view : Model -> Html Msg
view model =
div []
[ Textfield.render Mdl
[ 2 ]
model.mdl
[ Textfield.label "Floating label"
, Textfield.floatingLabel
, Textfield.text_
]
[]
, Textfield.render Mdl
[ 5 ]
model.mdl
[ Textfield.label "Enter password"
, Textfield.floatingLabel
, Textfield.password
]
[]
]
main : Program Never Model Msg
main =
Html.program
{ view = view
, update = update
, subscriptions = \_ -> Sub.none
, init = ( model, Cmd.none )
}
Remember that you have to add to your index.html links to the css of mdl.