Create R shiny bindings at runtime for cloned elments?

76 Views Asked by At

I am using R's sortable package to create a drag and drop report builder (where the user can drag various tools into the report). My issue is that any given tool might be used more than once. So I use the clone feature of sortable to clone the tool when it is dropped into the report.

The challenge is that the cloned element has the same id as the original (it is just an exact copy of the element created by SortablJS). Needless to say, this messes up any reactive elements in the tool and does not create any unique bindings to the new element.

I could change the id(s) with javascript within the onClone event. But I do not know how to create the new shiny reactive bindings to the new id(s). One option would be to create a bunch of dummy bindings at startup ("output1", "output2", "output3", etc.), and then as those ids appear in the DOM as a result of cloning (followed by changing the id names within the onClone event), things should sort themselves out. But that seems like a hack. Are there other ways of doing this purely at runtime without dummy bindings?

Here is reprex of the situation:

library(shiny)
library(sortable)

ui <- fluidPage(
    tags$div(HTML("<h3>Drag widget from here:</h3>"),
        tags$div(
          id = "toolbox",
          tags$div(
              textInput("something", label = "Enter something:"),
              textOutput("out")
          )
        )
    ),
    tags$div(HTML("<h3>To Below Here:</h3>"),
        tags$div(
         id = "workspace"
        )
    ),
    sortable_js(
        "toolbox",
        options = sortable_options(
            group = list(
                pull = "clone",
                put = FALSE,
                name = "draggable_tools"
            )
        )
    ),
    sortable_js(
        "workspace",
        options = sortable_options(
            group = list(
                name = "draggable_tools"
            )
        )
    )
)

server <- function(input, output) {
    output$out <- renderText({
        paste("You entered: ", input$something)
    })
}

shinyApp(ui, server)

EDIT: So my proposed (admittedly naïve) work around above does not work either, as creating DOM elements after the fact does not create/preserve the necessary wiring. My current thought is that what I want here is Not Possible™ with sortable, and I will have to rely on clicks and insertUI(...) rather than drag and drop (though the inserted elements could still be moved around within the destination div with sortable...just not dropped there to begin with).

0

There are 0 best solutions below