Since I use dash, I have some annoying problems with the style_header parameter of the dash_table.Datatable component.
Indeed, some of them like the colors / background colors work while others like width do not work. It seems that it is linked to the other variable 'fixed_rows' which, when set to true (to make the dashboard header fixed), blocks the width selection.
I've tried with all the versions of dash (from 1.20.0 to the very last one when I write these lines, 2.5.1) and always have this problem.
See below :
With fixed_rows={'headers': True} :
image
With fixed_rows not activated :
image
My code :
from dash import Dash
import dash_bootstrap_components as dbc
import dash_html_components as html
import dash_table
from tools.visual import colors
cols = ['ColumnA', 'ColumnB', 'ColumnC']
app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions=True)
app.layout = html.Div(children=[
# Dashboard
html.Div(id="table", children=[
dash_table.DataTable(
columns=[{"id": i, "name": i} for i in cols],
style_header={
'backgroundColor': colors['bg_board'],
'color': colors['text_category'],
'fontWeight': 'bold',
'textAlign': 'center'
},
style_cell={
'textAlign': 'center',
'whiteSpace': 'normal',
'height': 'auto',
'width': '200px'
},
style_cell_conditional=
[
{
'if': {'column_id': 'Maturity'},
'backgroundColor': colors['bg_board'],
'color': colors['text_category'],
}
],
style_table={
'overflow': 'auto',
},
fill_width=False,
# fixed_rows={'headers': True},
css=[{"selector": ".show-hide", "rule": "display: none"}],
id='tbl'
)
]),
])
if __name__ == '__main__':
app.run_server(debug=False, host='0.0.0.0', port=5026)
You probably solved your issue but here is my take on it for future reference.
style_cell works for headers and data, style_data works for data cells, style_header works for data.
For a fixed size to work, you need to use the 3 parameters as following:
style_cell={
# all three widths are needed
'minWidth': '75px', 'width': '75px', 'maxWidth': '75px',
},
)
Related
I'm working on creating an interactive dashboard using dash. There is a default dataframe(say dashtable1) and everytime I click a column of dashtable1 I want the graph to update and everytime I click on a row I want another dash table(dashtable2) to update. I have partially achieved this. The following is the code snippet:
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 Input, Output, State
app = dash.Dash(__name__, external_stylesheets = [dbc.themes.BOOTSTRAP], prevent_initial_callbacks=True)
app.layout = html.Div([dbc.Row(
[dbc.Col(html.Div(id='graph', style = {'height' : 400 , 'width' : 1750}), width = 9),dbc.Col(html.Div(id='action-df'), width = 3)]
#app.callback(
Output(component_id='action-df', component_property='children'),
[Input(component_id='datatable-interactivity', component_property="derived_virtual_data"),
Input(component_id='datatable-interactivity', component_property='derived_virtual_selected_rows'),
Input(component_id='datatable-interactivity', component_property='derived_virtual_selected_row_ids'),
Input(component_id='datatable-interactivity', component_property='selected_rows'),
Input(component_id='datatable-interactivity', component_property='derived_virtual_indices'),
Input(component_id='datatable-interactivity', component_property='derived_virtual_row_ids'),
Input(component_id='datatable-interactivity', component_property='active_cell'),
Input(component_id='datatable-interactivity', component_property='selected_cells')])
def update_df(all_rows_data, slctd_row_indices, slct_rows_names, slctd_rows,
order_of_rows_indices, order_of_rows_names, actv_cell, slctd_cell):
dff = pd.DataFrame(all_rows_data)
dff.dropna(inplace =True)
action-df.iloc[slctd_row_indices[0],:]
return html.Div(children = [html.Div([
dash_table.DataTable( id = 'action-df',
data=action_df.to_dict('records'),
page_size=10,
fixed_rows={'headers': True},
style_cell_conditional=[ # align text columns to left. By default they are aligned to right
{
'if': {'column_id': c},
'textAlign': 'left'
} for c in action_df.columns
],
style_data={ # overflow cells' content into multiple lines
'whiteSpace': 'normal',
'height': 'auto'
},
columns=[{'name': ["Changeable Parameters",i], 'id': i} for i in action_df.columns ],
cell_selectable = True,
style_data_conditional=[{
'if': {'row_index': 'odd'},
'backgroundColor': 'rgb(88, 237, 217)'
}, {'if': {'row_index': 'even'},
'backgroundColor': 'rgb(143, 255, 240)'}],
style_header={
'backgroundColor': 'rgb(0, 219, 190)',
'fontWeight': 'bold',
'text-align': 'center'},
fill_width = False,
style_cell={
'height': 'auto',
# all three widths are needed
'minWidth': '180px', 'width': '180px', 'maxWidth': '180px',
'whiteSpace': 'normal',
'font_family': "Coda Caption",
'font_size': '18px'
},
style_table={
'overflowY': 'scroll'},
merge_duplicate_headers=True
)
])
)
#app.callback(Output(component_id = 'graph',component_property = 'children'),
[Input(component_id = 'datatable-interactivity', component_property = 'selected_columns' )]
)
def linechart(slctd_columns):
if 'TIMESTAMP' not in slctd_columns:
fig = px.line(df_merged.iloc[:30,:], x="TIMESTAMP", y= slctd_columns)
fig.update_layout(
title="PARAMETER VARIATION OVER THE LAST MONTH",
xaxis_title="TIMESTAMP",
yaxis_title= str(slctd_columns[0]),
font=dict(
family="Coda Caption",
size=18,
color="#121212"
)
)
return dcc.Graph(id = 'graph',
figure = fig)
This code perfectly works out when I select a row/column for the first time, but stops updating after that. I'm new to Dash, so any help would be highly appreciated!
I created a Dash application to present some data.
I've got a DataTable showing on the front page and I've set pagination configurations for it.
The DataTable is great except for 2 things:
The button in charge of moving to the next pages and back is positioned way off in relation to the table
The beginning and end of the table (the cells) are not showing well when I decrease the monitor size (non responsive)
I've added a picture to help understand these issues:
This is on my wide screen, if I switch to my phone then the beginning of the ID column is not showing and the page navigator buttons are not showing as well.
This is the code I use to create this, the DataTable is wrapped inside the main container div:
import dash_html_components as html
from dash_table import DataTable
...
The code for the datatable:
active = DataTable(id='active-strategies',
columns=[{
"name": col,
"id": col
} for col in dummy_table.columns],
data=dummy_table.to_dict('records'),
page_current=0,
page_size=15,
filter_action="native",
style_table={
'width': '80%',
'margin': 'auto',
'padding': '0 5px',
'overflowX': 'auto',
'overflowY': 'auto',
},
style_cell={
'padding': '0 10px',
'fontSize': '14px',
'textAlign': 'center',
'whiteSpace': 'normal',
},
style_data={},
style_as_list_view=True)
And the div it's wrapped in:
layout1 = html.Div([
...
active,
...
],
style={
'display': 'flex',
'flexDirection': 'column',
'justiyContent': 'center',
'alignItems': 'center',
'margin': 'auto',
'overflow': 'hidden',
'marginBottom': '200px'
})
Adding 'margin-left': '5%', 'margin-right': '5%' and 'width' : '90%' in your html.Div style should fix this issue! Play around with the values, of course.
I have a plotly histogram with a shape in the background. How can I make the background object right/left dragg-able?
import numpy as np
import plotly.graph_objects as go
# generate data
data = np.random.normal(0,10,500)
# plot histogramm
fig = go.Figure()
fig.add_trace(go.Histogram(x=data))
# add shape
fig.add_shape(dict(type="rect", xref="x", yref="paper",
x0=-22, x1=22,
y0=0, y1=1,
fillcolor="Gray", opacity=0.3,
layer="below", line_width=0, editable=True))
current output:
desired output: have the shape-object draggable.
Edit: The background object doesnt have to be a "shape"
Disclaimer: I am not very experienced in Dash, but this was the only way I could implement a movable shape. I relied heavily on this answer by chriddyp in the Plotly Community forum. The parameters of dcc.Graph are pretty similar to go.Figure.
One thing to note is that only when your cursor is very much interior to the shape are you able to drag it, but if you hover anywhere else closer to the borders, clicking and dragging will change your shape's dimensions rather than move it, which may or may not not be the behavior you are after. Anyone who uses Dash regularly- feel free to update/improve upon my answer as needed.
import numpy as np
import json
from textwrap import dedent as d
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
# generate data, set seed for reproducibility
np.random.seed(42)
data = np.random.normal(0,10,500)
app = dash.Dash(
__name__,
external_stylesheets=[
'https://codepen.io/chriddyp/pen/dZVMbK.css'
]
)
styles = {'pre': {'border': 'thin lightgrey solid', 'overflowX': 'scroll'}}
app.layout = html.Div(className='row', children=[
dcc.Graph(
id='basic-interactions',
className='six columns',
figure={
'data': [{
'x': data,
'name': 'Trace 1',
'type': 'histogram'
}],
'layout': {
'shapes': [{
'type': 'rect',
'x0': -22,
'x1': 22,
'xref': 'x',
'y0': 0,
'y1': 50,
'yref': 'y',
'fill': 'toself',
'line': dict(
color="Gray",
width=0.5,
),
'fillcolor': 'Gray',
'layer': 'below'
}]
}
},
config={
'editable': True,
'edits': {
'shapePosition': True
}
}
),
])
if __name__ == '__main__':
app.run_server(debug=True)
I have a Data Table in Dash (python) that works very well. I would like the scroll bar to default to the right - that is, to show the most right information in the data table. The current default is the scroll bar is set to the left. I am using time series data for a finance table, so I want to show the most current year, which is all the way to the right (don't want to make it left) and have the scroll bar set so that its show the right and then you would need to scroll to the left to see the left.
Here is what I have and it works fine except for the issue above:
app = dash.Dash(__name__)
app.layout = dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict('records'),
fixed_columns={'headers': True, 'data': 1},
fixed_rows={'headers': True, 'data': 1},
# style_cell={'textAlign': 'left'},
style_cell={'fontFamily': 'sans-serif', 'fontSize': '12px', 'border': '0px'}, #, 'boxShadow': '10 0'},
style_table={'minWidth': '60%'},
style_cell_conditional=[
{
'if': {'column_id': i},
'textAlign': 'left',
'fontWeight': 'bold'
} for i in ['$ in millions']#, 'C']
],
style_header={
'backgroundColor': 'white',
'fontWeight': 'bold',
'borderBottom': '1px solid black'
},
# style_as_list_view=True,
)
# $ in millions
if __name__ == '__main__':
app.run_server()
If you were making your Dash application using JavaScript, the solution would have been pretty straight forward, unfortunately there is no straight forward answer other than creating 'assets' folder and creating a HTML file with a function to scroll right. The easiest way to tackle this, in my opinion, is to just re-arranging the columns backward by doing df = df.columns[::-1] or by slicing and rearranging the df.
Sorry i'm very new to dash, css, html coding.
i'm using Dash on Python and i would like a simple full page background with an image.
i'm using this CSS: https://codepen.io/chriddyp/pen/bWLwgP.css
i tried to use different CSS (https://necolas.github.io/normalize.css/8.0.1/normalize.css) beacuse i read it was a margin problem but it didn't work
i've read a lot of discussion about this issue but i wasn't able to fix it for my purposes
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__,
external_stylesheets = external_stylesheets)
app.title = "Q"
colors = {'background': '#ffffff',
'bg_home': '#666666',
'text': '#ffa500',
'background_plot': '#cccccc',
'text_plot': '#000000'}
app.config['suppress_callback_exceptions']=True
image = 'url(https://c.wallhere.com/photos/a1/fc/1920x1080_px_Albert_Einstein_Formula_mathematics_physics_science_Special_Relativity-549404.jpg!d)'
app.layout = html.Div(
className='row',
style={
'verticalAlign':'middle',
'textAlign': 'center',
'background-image':image,
},
children= [
html.Div(
id='Username',
style={'textAlign': 'center',
'verticalAlign':'middle',
},
children= [
html.H3('Login',
style={'textAlign': 'center',
'color':'orange',
'fontWeight': 'bold',
},
),
html.Div(
className='row',
children=[
dcc.Input(id = 'user',
style={'margin-top':20},
type='text',
placeholder='Username'
)
]
),
html.Div(className='row',
children=[
dcc.Input(id = 'psw',
style={'margin-top':20},
type='text',
placeholder='Password'
)
]
),
html.Div(className='row',
children=[
html.Button('Login',
id='log',
style={'background-color':'white',
'color':'black',
'margin-top': 20,
'textAlign':'right'},
),
]
)
])
]
)
if __name__ == '__main__':
app.run_server(debug=True,host='0.0.0.0',port=8050)
i'm not gettin error but i just get 1/3 (more or less) of the page with background image and login Div, the rest of the page completely white.
I just would like a full page with background image and login in the center
Thank you all
In css body tag defines the document's whole body and the div is a part of it, there are two ways to get this working.
Make the div to cover the entire page and set the image to the div
Refer here:
Making a div that covers the entire page
Modified bit of code,
className='row',
style={
'verticalAlign':'middle',
'textAlign': 'center',
'background-image':image,
'position':'fixed',
'width':'100%',
'height':'100%',
'top':'0px',
'left':'0px',
'z-index':'1000'
},
Modify the body tag in theexternal_stylesheet to have the property background-image,
body {
'background-image' : url(url!d);
}
There are 2 ways to get this done:
Note: Is is a good practice to create a folder 'assets' in the program's root directory, and place your image inside it.
Method-1:
app.layout = html.Div([ ...fill your children here... ],
style={'background-image': 'url(/assets/image.jpg)',
'background-size': '100%',
'position': 'fixed',
'width': '100%',
'height': '100%'
})
Method-2:
app.layout = html.Div([ ...fill your children here... ],
style={'background-image': 'url(/assets/image.jpg)',
'background-size': '100%',
'width': '100vw',
'height': '100vh'
})