materialsproject/crystaltoolkit

Dash's new pattern-matching callbacks require component ids to be dictionaries

jordanpburns opened this issue · 4 comments

From https://dash.plotly.com/pattern-matching-callbacks: "The pattern-matching callback selectors MATCH, ALL, & ALLSMALLER allow you to write callbacks that respond to or update an arbitrary or dynamic number of components."

However, this functionality requires that component ids are dictionaries, not strings. In addition, Input and State inside of callbacks need to be able to accept dictionaries as well.

Would it be difficult to implement these changes in crystal toolkit?

Crystal Toolkit is already using pattern-matching callbacks! :)

We could be using them more extensively however, probably to our benefit (see #265). The problem is that last I checked you cannot write client-side pattern-matched callbacks. If this changes, I think it'd be a good time to re-visit.

The problem is that last I checked you cannot write client-side pattern-matched callbacks. If this changes, I think it'd be a good time to re-visit.

Still no support for that if you're referring to plotly/dash#1461?

But afaict, CT only has 3 client-side callbacks, all in crystal_toolkit/components/structure.py which by the looks of them wouldn't benefit from pattern matching anyways since they only update a single structure component?

Pattern matching is also used for anything that uses the "keyword-argument-style" inputs, e.g. .get_bool_input() etc. This is used for the control panels for a few apps, the transformations, etc.

The benefit of adopting pattern matching everywhere is that currently a unique callback is defined for every instance of a given component, e.g. if you have ctc.StructureMoleculeComponent(id="my-structure-1") and ctc.StructureMoleculeComponent(id="my-structure-2"), two sets of callbacks are defined.

Apart from unnecessarily bloating the list of callbacks, this also means that you can't just drop in ctc.StructureMoleculeComponent(id="my-structure-3").layout() in a callback somewhere--it has to be instantiated first on app creation so that the necessary callbacks are defined (this is usually done in an __init__ for the relevant app).

If, instead, we used pattern-matched callbacks throughout, we would only need the one set of callbacks defined, and returning ctc.StructureMoleculeComponent(id="my-structure-3").layout() from a callback without instantiating ctc.StructureMoleculeComponent(id="my-structure-3") first, would be no problem at all.