Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#828 breaks maintaining selected columns upon re-render #1125

Closed
epruesse opened this issue Feb 24, 2024 · 3 comments · Fixed by #1126
Closed

#828 breaks maintaining selected columns upon re-render #1125

epruesse opened this issue Feb 24, 2024 · 3 comments · Fixed by #1126

Comments

@epruesse
Copy link
Contributor

var cleanSelectedValues = function() {
changeInput('rows_selected', []);
changeInput('columns_selected', []);
changeInput('cells_selected', transposeArray2D([]), 'shiny.matrix');
}
// #828 we should clean the selection on the server-side when the table reloads
cleanSelectedValues();

The above code was added in response to #828, where the server side was not cleared when the table is reloaded and the Select extension is in use. However, this code doesn't sync, it wipes. So if user code, e.g. via callback, attempts to retain the row selections made by the user, only updating other parts of the table, the server side gets out of sync again. And since this piece of code is executed after the callbacks, it overrides any Shiny.setInputValue() that might be used to correct the server side.

Example:

DT::datatable(
  callback = DT::JS(
    paste0("var rows = [", rows_str, "];"),
    paste0("var reactvar = '", id, "_rows_selected';"),
    "table.rows(rows).select();",
    "Shiny.setInputValue(reactvar, rows);"
  )
)

The above sets the selected rows according to the numbers in row_str, e.g. 0,1,2, then would send the same back to Shiny (yes, probably off by one due to R's 1-indexing). However, the message is overwritten by the mentioned code.

I'd suggest removing the cleanSelectedValues() call entirely, and instead calling the updateSelectedRows() family of functions defined directly below. That way, R get's a copy of the actual status.

If anyone has a suggestion for a workaround, I'm all ears... Perhaps having a hook towards the end of the renderValue function would be helpful, to be able to override it when it does something other than necessary in a specific case.

@yihui
Copy link
Member

yihui commented Feb 24, 2024

Since it's been too long and the original code was written by another author who is no longer active here, I'm not sure what we should do about it. Is this issue more or less the same as #918? If so, I feel it makes sense to make the behavior optional via a user-provided option. Unfortunately I'm not familiar with this part of code and have to rely on someone else's judgment/pull request... Thanks for the report anyway!

@epruesse
Copy link
Contributor Author

One other simple option would be to add a way to execute JS at the very end of the renderValue function. Preferably with full access to the variables inside that function. That way, client code can just adjust things. May require client apps to be adjusted more with DT updates, but allows for more extensive meddling when needed.

@epruesse
Copy link
Contributor Author

@yihui See my minimal fix in PR #1126. This repairs it for me. It also should break anything for anyone. It merely sends the actual state if on client side table with Select extension, making it so the _xxx_selected variables actually match the table state. I don't know enough about the code and other combinations to dare to change this more broadly.

@yihui yihui linked a pull request Feb 27, 2024 that will close this issue
yihui pushed a commit that referenced this issue Mar 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants