Open europa502 opened 2 years ago
Hi ! Thank you for the support ❤️ !
Indeed you can use callbacks to get the position of elements on the dashboard!
GridLayout
you can access it through the layout
propertyResponsiveGridLayout
you can access it through the current_layout
and all_layouts
properties (as the layout depends on the screen size).
@app.callback(
Output('layout_callback', 'children'),
Input('draggable', 'layout'))
def update_figure(layout):
return(str(layout))
BTW thank you for your feedback 👍, I will update examples in the repository to make it more obvious how to use callbacks with GridLayout and ResponsiveGridLayout.
Below is a complete example with the callback displaying the layout on the page:
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
import dash_draggable
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
server = app.server
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv')
app.layout = html.Div([
html.H1("Dash Draggable"),
html.Div(id='layout_callback'),
dash_draggable.GridLayout(
id='draggable',
children=[
html.Div(children=[
dcc.Graph(
id='graph-with-slider',
responsive=True,
style={
"min-height":"0",
"flex-grow":"1"
}),
dcc.Slider(
id='year-slider',
min=df['year'].min(),
max=df['year'].max(),
value=df['year'].min(),
marks={str(year): str(year) for year in df['year'].unique()},
step=None)
],
style={
"height":'100%',
"width":'100%',
"display":"flex",
"flex-direction":"column",
"flex-grow":"0"
}),
]
),
])
@app.callback(
Output('graph-with-slider', 'figure'),
Input('year-slider', 'value'))
def update_figure(selected_year):
filtered_df = df[df.year == selected_year]
fig = px.scatter(filtered_df, x="gdpPercap", y="lifeExp",
size="pop", color="continent", hover_name="country",
log_x=True, size_max=55)
fig.update_layout(transition_duration=500)
return fig
@app.callback(
Output('layout_callback', 'children'),
Input('draggable', 'layout'))
def display_layout(layout):
return(str(layout))
if __name__ == '__main__':
app.run_server(debug=True, port='5080')
@MehdiChelh ,
Thanks a lot for helping me out with the solution. The example you provided would be enough if we were to track the position of only one element in the the layout, but if we were to track the position of more than one element within the layout, I think it'd become difficult, since the list of dict of layout properties don't have ant identifiable fields, like element id.
For Eg.
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
import dash_draggable
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
server = app.server
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv')
app.layout = html.Div([
html.H1("Dash Draggable"),
html.Div(id='layout_callback'),
dash_draggable.GridLayout(
id='draggable',
children=[
html.Div(children=[
dcc.Graph(
id='graph-with-slider',
responsive=True,
style={
"min-height":"0",
"flex-grow":"1"
}),
dcc.Slider(
id='year-slider',
min=df['year'].min(),
max=df['year'].max(),
value=df['year'].min(),
marks={str(year): str(year) for year in df['year'].unique()},
step=None)
],
style={
"height":'100%',
"width":'100%',
"display":"flex",
"flex-direction":"column",
"flex-grow":"0"
}),
html.Div(children=[
dcc.Graph(
id='graph-with-slider1',
responsive=True,
style={
"min-height":"0",
"flex-grow":"1"
}),
dcc.Slider(
id='year-slider1',
min=df['year'].min(),
max=df['year'].max(),
value=df['year'].min(),
marks={str(year): str(year) for year in df['year'].unique()},
step=None)
],
style={
"height":'100%',
"width":'100%',
"display":"flex",
"flex-direction":"column",
"flex-grow":"0"
}),
]
),
])
@app.callback(
Output('graph-with-slider', 'figure'),
Input('year-slider', 'value'))
def update_figure(selected_year):
filtered_df = df[df.year == selected_year]
fig = px.scatter(filtered_df, x="gdpPercap", y="lifeExp",
size="pop", color="continent", hover_name="country",
log_x=True, size_max=55)
fig.update_layout(transition_duration=500)
return fig
@app.callback(
Output('layout_callback', 'children'),
Input('draggable', 'layout'))
def display_layout(layout):
return(str(layout))
if __name__ == '__main__':
app.run_server(debug=True, port='5080')
By running the code I'd get an output that looks like this -
From the above string it is difficult to figure out which dict in the list represents which div (unless you know the initial position of the divs from the code). I guess it'd be really simple to just add the id prop to the layout dict?
Please let me know what you think about this.
Cheers, Abhijit
I just passed the id of div and I got it returned as 'i' in the layout dict. This should work I guess. Also can you replace 'i' with 'id' if its not meant for properties like 'index' or anything else?
Thanks, Abhijit
Is it possible to access the position of elements added in dash_draggable.GridLayout() from a callback? I tried accessing the children but I guess the array is not sorted according to position of defined elements when returning in callback?
I know 'Drag and drop items in list (trello-like)' is in your action items and most probably the list will be sorted based on the position of the elements in the childern, but I can't wait till that feature is implemented in the next release.😬
BTW, awesome work! Love it.