opened 10:49PM - 25 Mar 21 UTC
If we use `renderUI` to load some large UI and call the rendered UI associated s…erver functions after the `renderUI`, it will likely cause problems because the UI is just sent to the client and input-binding registration is still ongoing.
Simple example:
```r
ui <- fluidPage(
actionButton("a", "add UI"),
uiOutput("ui_out")
)
loadserver <- function(input, output, session){
if(input$n1000 > 0) print(1)
#### many other things
}
server <- function(input, output, session) {
observeEvent(input$a, {
output$ui_out <- renderUI({
lapply(1:1000, function(i) {
numericInput(paste0("n", i), paste0("n", i), value = 0)
})
})
loadserver(input, output, session)
})
}
shinyApp(ui, server)
```
I know I can add `req` to prevent the error, but please don't struggle with this. Just imagine `loadserver` comes from a package and you can't do anything in the function. The normal preloading has no problem (load the required UI and server on start), but only causes problems with this dynamic loading. So, let's just say I want to wait until the UI loading and input-binding is complete and do something in the server.
Can we have some options:
1. Make `renderUI` sync ("blocking") before executing the next line. Now it is more like async, it only sends out the UI as a message and goes on to the next line. It doesn't know if the input-binding is complete or the expected inputs are registered in the current shiny session. Add an option like `renderUI(wait = TRUE)`
2. I tried to watch for "shiny:value" event on js, but it only tells me the client has received the new UI, but still, it doesn't tell me the loading is complete or shiny session has all the new inputs registered. If we could have all inputs to be registered in "shiny:value", I can watch for them.
``` js
//shiny:value
{
toBeBound : [id1, id2, ...],
...
};
var binds;
var bound = 0;
$(document).on('shiny:value', function(e) {
binds = e.toBeBound;
});
$(document).on('shiny:bound', function(e) {
if (binds.includes(e.target.id)) bound ++
});
setInterval(function() {
if (bound == binds.length) {
// load server
}
}, 1000);
```