OperatorTransform - List and dict operations, and partial component property updates

I have just released dash-extensions==0.1.5, which includes the (new) OperatorTransform. The OperatorTransform makes it possible perform partial component property updates, e.g. change the color of a trace,

@app.callback(OperatorOutput("graph", "figure"), Input("dd", "value"))
def change_color(color):
    if color is None:
        raise PreventUpdate
    return Operator()['data'][0]['marker']['color'].assign(color)

without exchanging all data between the client and the server. It also enables list and dict operations, e.g. appending an element to a list,

@app.callback(OperatorOutput("log", "children"), Input("btn", "n_clicks"))
def append_to_log(n_clicks):
    log_entry = f"{datetime.datetime.now().isoformat()}: BUTTON CLICKED (n_clicks={n_clicks})"
    return Operator().list.append(dmc.ListItem(log_entry))

Hence, for properties that contain a large amount of data, there is potential for (significant) performance improvements. You can read more and see a few complete examples in the documentation :slight_smile:

@AnnMarieW @chriddyp @alexcjohnson I finally got it wrapped up :grin:

8 Likes

Hey @Emil - Wow this is so cool!

I see in your docs that you can do chained operations. Can you also use loops, like in this case: Dash datatable - updating a single row takes a long time (with MWE)

Very cool!

Could you describe how the Operator() object works? Or what types of syntax is allowed?

@chriddyp Thanks! To perform an operation, a callback must return an instance of an Operator object. In addition to the (normal) assign operation, the current implementation supports list operations (append, extend, insert, remove, pop, clear, sort, reverse) via the following syntax,

Operator().list.append(...)

and dict operations (set, pop, update, clear) via a similar syntax,

Operator().dict.set(...)

In addition, standard square bracket syntax is supported for targeting sub elements of list or dicts,

Operator()['data'][0]['marker']['color'].assign(color)

It is also possible to create a chain of operations via syntax like,

operator = Operator()
operator.list.append(n_clicks)
operator.list.sort()

In essence, the OperatorTransform works by adding a client side callback, which carries out the operation specified by Operator object returned by the (normal) callback.

1 Like

@AnnMarieW Thanks! You could use a (normal Python) loop to construct a chain operations, but the current implementation doesn’t include a syntax for a “loop operation”. If you really need to do loops, I think a client side callback might be more appropriate :slight_smile:

1 Like