Bring Drag & Drop to Dash with Dashboard Engine. 💫 Learn how at our next webinar!

How to integrate both Clientside and Serverside callback code for same target Output?

To describe what I am trying to do, consider the below UI

  1. Card(s) are bootstrap card components.
  • It has ‘X’ button to delete the card from the container named ‘body-container’
  • It has ‘↑’ button to move the card up in the container. Just like Jupyter notebook, where we move cell up or down
  • It has ‘↓’ button to move cell down

Now I have implemented all this as clientside callbacks for some specific reasons and speed and can’t make it server-side.

Now, there is one dropdown, user can select a specific element from the dropdown and that ‘Card’ will be added into the ‘body-container’ children. Now I have all the components as a python dict just like mentioned here. Now How can I integrate this code? I can not write server side callback because dash won’t allow me duplicate callback output for Output('body-container', 'children'). How to resolver this issue?

Here is a pseudo code–

Cards = {
  'card A': CardA(),
  'card B': CardB(),
  'card C': CardC(),
}

app.clientside_callback(
    """
    function(n_clicks_1, n_clicks_2, n_clicks_3, children) {
        // javascript code
       // some operation on children
        return children;
    }
    """,
    Output('body-container', 'children'),
    [Input({'type': 'delete-card', 'id': ALL}, 'n_clicks'),
     Input({'type': 'down-card', 'id': ALL}, 'n_clicks'),
     Input({'type': 'up-card', 'id': ALL}, 'n_clicks')],
    State('body-container', 'children'),
    prevent_initial_call=True
)


@app.callback(
    Output('body-container', 'children'),
    Input('main-app-dropdown', 'value'),
   State('body-container', 'children'),
    prevent_initial_call=True
)
def add_card_to_body(value, children):
    # return a spcific child
   # get desired card from Card dictionary
    children.append(child_I_want_to_add)
    return children

You could try the MultiplexerTransform,

Unfortunately I am not creating app object. I am using dataiku, and it provides the app object. Also The MultiplexerTransform does not support the MATCH and ALLSMALLER wildcards. But I am widely using them, so it will not work in my case :sob:

For Dataiku I have made a workaround. But I haven’t figured out a nice way to handle MATCH and ALLSMALLER wildcards (apart from replacing them by ALL and adopting the code accordingly). The only other immediate solution that I am aware of is to implement the multiplexer strategy by hand (i.e. mimic what the MultiplexerTransform does directly in code). However, that’s very tedious (and error prone) so I wouldn’t recommend it.

Oh okay, thanks for the information. Do you know how to convert the dash objects to relevant HTML component.
What I was trying to do is

app.clientside_callback(
    """
    function(n_clicks_1, n_clicks_2, n_clicks_3, children) {
        // javascript code
       // some operation on children
       const container = document.getElementById('drag-container');
       container.innerHTML = children;
        return '';
    }
    """,
    Output('dummy-container', 'children'),
    [Input({'type': 'delete-card', 'id': ALL}, 'n_clicks'),
     Input({'type': 'down-card', 'id': ALL}, 'n_clicks'),
     Input({'type': 'up-card', 'id': ALL}, 'n_clicks')],
    State('body-container', 'children'),
    prevent_initial_call=True
)

But it gives the output webpage as

[Object, Object, Object,....]

How to render those components to HTML? I suppose dash object inside python and inside javascript (in this case) has different render methods to convert them to dom objects.
They look something like this –

image

It is possible, but not pretty,

1 Like