Force synchronous dataTableProxy operations?

In a Shiny app I have a {DT} in which I update the data via the replaceData(dataTableProxy, data, ...) paradigm. Once the data have been replaced, I'd like to (conditionally) select a row. The straight-forward approach looks like so:

output[["dt"]] <- DT::renderDataTable(my_dt, server = TRUE)
dt_proxy <- DT::dataTableProxy("dt", deferUntilFlush = TRUE)
# ...
shiny::observe({
  new_data <- some_new_reactive_data()
  DT::replaceData(dt_proxy, new_data, clearSelection = "all")  # clear selection because we'll highlight a new row
  DT::selectRows(dt_proxy, my_reactive_row_index(), ignore.selectable = TRUE)
})

After banging my head against the wall for a long while trying to figure out why the selectRows() call wasn't selecting the row, I managed to figure out that within the browser the selectRows() method was executing before the replaceData() method on the DataTable. The net result is the row gets selected then is immediately cleared by the replaceData() execution.

I could conceivably disable the clearSelection argument in the replaceData() call, but this seems risky to me as I also want to ensure that only the specified rows in my selectRows() call are selected. Clearing the rows first via two successive selectRows() calls seems like it could also then work, but it's the same challenge as with the original case: I'm now unsure if there's a guaranteed order-of-execution on the browser of the DT's proxied calls.

Has anyone encountered this async/out-of-order behavior before with {DT}; and know of a way to try to guarantee ordering browser-side?

I've mostly figured out the problem, but am still curious about the possible solutions.

The problem itself is that replaceData() (and its sibling, reloadData()) relay the message for the browser-side DataTable to re-fetch data from the AJAX endpoint that DT exposes via Shiny. This happens asynchronously, so despite this instruction being executed prior to the browser executing the selectRows() method, the new data arrives after both of these instructions have completed.

Ideally, there'd be a way to register a callback once the data has been replaced: either a client-side JS callback, or even a server-side R callback (which would simply react to a sentinel input updated by a client-side callback upon data reload). DataTables (the JS library) does expose a callback on ajax.reload(), but {DT}'s replaceData() unfortunately doesn't seem to expose this option.

This seems like a common use case to me; surely I'm not the first to encounter this issue with {DT}'s proxy methods?

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.