How to use `document.querySelector` with non-string IDs in `clientside_callback`?

Hello – I am attempting to select the contents of an agGrid table to pass to a third party library that converts html elements to images (html2canvas).

The pattern I am using is roughly

def register_screenshot_callback(
    button_id: str | dict[str, _Wildcard | str],
    *table_ids: Collection[str | dict[str, _Wildcard | str]]
):
    clientside_callback(
    """
(_, ...ids) => {
  ids.map((id) => {
    dash_ag_grid.getApiAsync(id).then((gridApi) => {
      // THIS IS WHERE MY PROBLEM IS -- this only works with string IDs.
      // I have also tried using the `stringifyId` function from 
      // https://community.plotly.com/t/adding-component-via-clientside-callbacks/76535/5
      let el = document.querySelector(`div#${id}`);

      const initialHeight = el.style.height.toString();
      const initialWidth = el.style.width.toString();
      // ^ these guys needed to reset the height of the grid later.
      // do more stuff with the grid
      html2canvas(el).then(
        // put the output in a new window
      );
    });
  });
  return dash_clientside.no_update;
}
    """,
        Output(table_ids[0], "id"),
        Input(button_id, "n_clicks"),
        *[State(id, "id") for id in table_ids],
        prevent_initial_call = True
    )

Is there a supported way to do this? Also linking the issue referenced in the code snippet again to boost visibility.

Hello @ctdunc,

For the grid, you can use this:

el = dash_ag_grid.getApi(id).gridBodyCtrl.eBodyViewport.parentNode.parentNode.parentNode.parentNode.parentNode

At least for the time being.

You could also stringifyId and then replace the {} from it with nothing and query it like this:

document.querySelector(`div[id*='${stringifyId(id).replace('{','').replace('}','')}']`)

I’d also suggest a test to make sure that the id is what you are looking for, something like:

el.id == stringifyId(id)

Just to be sure you didnt get some other matches, and possibly only use this method if the id is an object vs a string.

Thanks for the fast reply. The first option seems more likely to work consistently since we’ll always have this grid API + use complex pattern matching callbacks very frequently.

Worth noting that my LSP complains about the suggested solution. It’s probably nbd since the ag grid version is pinned, but worth noting.

BTW – do you think this is worth opening a feature request for? It would be great to have this officially supported in dash_clientside, perhaps as dash_clientside.querySelector or something similar.

You could ask, it could be something like dash_clientside.get_component_by_id. Just not sure if it would work 100%. And that may be more of the concern of plotly.

Plus, while this works for dag, dcc and html. There are some interesting dynamics when it comes to dmc and possibly dbc.