my goal:
I want to arrange the buttons any way I want (drag and drop via JavaScript) and when I press the ‘Show new order’ button I want to pick up the displayed order (show in ‘label2’ in this example).
Current situation:
I have three buttons in a html.div. Via a clientside_callback I can rearrange the buttons. I want to pick up this new arrangement in the next step. At this stage I can only change the html.label with id=‘label1’ in the browser, not the ‘children’ itself.
Approach:
Return the order from the variable ‘order_ids’ to the dcc.Store element with the id=‘store_order’. Unfortunately, all my attempts so far have failed.
index.py
import dash
import dash_bootstrap_components as dbc
from dash import dcc, html, Input, Output, State, ClientsideFunction
app = dash.Dash(
__name__,
suppress_callback_exceptions=True,
external_scripts=["https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.min.js"],
external_stylesheets=[dbc.themes.BOOTSTRAP]
)
app.layout = html.Div([
dcc.Store(id='store_order', storage_type='session'),
html.Div(
children=[
# Button No. 1
dbc.Button(
children='No. 1',
id='btn_1',
style={'margin': '10px', 'background-color': '#e9c46a', 'display': 'block'}
),
# Button No. 2
dbc.Button(
children='No. 2',
id='btn_2',
style={'margin': '10px', 'background-color': '#2a9d8f', 'display': 'block'}
),
# Button No. 3
dbc.Button(
children='No. 3',
id='btn_3',
style={'margin': '10px', 'background-color': '#264653', 'display': 'block'}
),
],
id='drag_container',
style={
'background-color': '#ffe8d6',
'width': '250px',
'border': '1px solid black',
'margin': '10px',
'padding': '10px',
}
),
html.Div(
[
dbc.Button('Show new order', id='btn_order'),
html.Br(),
html.Label('Label 1: '),
html.Label(id='label1'),
html.Br(),
html.Label('Label 2: '),
html.Label(id='label2'),
],
style={'margin': '10px'}
),
])
app.clientside_callback(
ClientsideFunction(namespace='clientside', function_name='make_draggable'),
Output('drag_container', 'data-drag'),
[Input('drag_container', 'id')],
[State('drag_container', 'children')],
)
@app.callback(
Output('label2', 'children'),
Input('btn_order', 'n_clicks'),
State('store_order', 'data')
)
def show_new_order(n_clicks, data):
# more code ...
return str(data)
if __name__ == '__main__':
app.run_server(debug=True)
assets/scripts.js
if (!window.dash_clientside) {
window.dash_clientside = {};
}
window.dash_clientside.clientside = {
make_draggable: function (id, children) {
setTimeout(function () {
var drake = dragula({});
var el = document.getElementById(id)
drake.containers.push(el);
drake.on("drop", function (_el, target, source, sibling) {
// a component has been dragged & dropped
// get the order of the ids from the DOM
var order_ids = Array.from(target.children).map(function (child) {
return child.id;
});
// in place sorting of the children to match the new order
children.sort(function (child1, child2) {
return order_ids.indexOf(child1.props.id) - order_ids.indexOf(child2.props.id)
});
// Trigger an update on the children property
label1.innerHTML = order_ids;
})
}, 1)
return window.dash_clientside.no_update
}
}
assets/dragula.css
.gu-mirror {
position: fixed !important;
margin: 0 !important;
z-index: 9999 !important;
opacity: 0.8;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
filter: alpha(opacity=80);
}
.gu-hide {
display: none !important;
}
.gu-unselectable {
-webkit-user-select: none !important;
-moz-user-select: none !important;
-ms-user-select: none !important;
user-select: none !important;
}
.gu-transit {
opacity: 0.2;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
filter: alpha(opacity=20);
}