kristofkelemen
kristofkelemen

Reputation: 79

How to refer to reactive element in ui.R in Shiny

I am making an app with drag and drop feature using the ShinyDND package. I would like to pass a list from input as a parameter of dragSetUI, a function that needs to be run in ui.R. I tried renderUI and uiOutput, and it almost works, but the dragged elements fail to be dropped in the drop area. As you can see in the example below, nonreactive choices work like charm. I tried creating a reactive object as well as text output, but I could not find documentation on how to refer to these objects in ui.R. Normally one would refer to output$x as "x" in Output, but here, if I add anything between quotes, it reads as string. I am really stuck with this.

library(shiny)
library(shinyDND)

nonreactive_choices<-as.list(c("a","b","c"))

ui <- shinyUI(
  mainPanel(
    textInput("choices","Put here a,b,c:"),
  dragSetUI("drag", textval = "reactive_choices"),
  dragSetUI("drag", textval = "choice_rv"),
  textOutput("reactive_choices"),
  dragSetUI("drag", textval = nonreactive_choices),
  dropUI("drop")
  )
)

server = shinyServer(function(input, output,session) {

   output$reactive_choices<-reactive({
     strsplit(input$choices,",")
     })

   observe({
     chlist<-strsplit(input$choices,",")
     choice_rv<-reactiveVal(chlist)
   })

})

# Run the application 
shinyApp(ui = ui, server = server)

Upvotes: 2

Views: 1060

Answers (2)

St&#233;phane Laurent
St&#233;phane Laurent

Reputation: 84529

Let's see why the renderUI approach does not work with shinyDND. An app using shinyDND is linked to the dragndrop.js file, which is in the shinyDND folder. In this file one can see:

$(document).ready(function(){
  ......
  $(".dragelement").on("dragstart",function(e){
    e.originalEvent.dataTransfer.setData("Text",e.target.id);
  });
  ......
});

This defines the action to perform on elements having class dragelement when a drag is starting, and this is defined when the document is ready. dragSetUI creates such elements.

When you use a dragSetUI inside a renderUI, this creates new elements of class dragelement. But the action defined on such elements in $(document).ready is not effective for these new elements, because this action has been defined just after the document is ready, and then before the effect of renderUI.

A solution consists in defining the action of the event dragstart inside the renderUI. This works:

library(shiny)
library(shinyDND)

nonreactive_choices<-as.list(c("a","b","c"))

ui <- shinyUI(
  mainPanel(
    textInput("choices","Put here d,e,f:"),
    dragSetUI("drag", textval = nonreactive_choices),
    uiOutput("dragset"),
    dropUI("drop")
  )
)

server = shinyServer(function(input, output,session) {

  reactive_choices <- reactive({
    strsplit(input$choices,",")[[1]]
  })

  output$dragset <- renderUI({
    tagList(
      dragSetUI("drag2", textval = as.list(reactive_choices())),
      tags$script('$(".dragelement").on("dragstart",function(e){
        e.originalEvent.dataTransfer.setData("Text",e.target.id);
      });'
      )
    )
  }) 
})

# Run the application 
shinyApp(ui = ui, server = server)

Upvotes: 1

kristofkelemen
kristofkelemen

Reputation: 79

Comment by @ismirsehregal helped me find the solution: shinyjqui can be used for my purposes and it seems to work from inside renderUI. Here is the edited code that does exactly what I needed.

library(shiny)
library(shinyjqui)


ui <- fluidPage(
  textInput("choices","Put here a,b,c:"),
  uiOutput("reactiveselect"),
  orderInput(inputId = 'drop', label = 'Reactive drop', items = NULL,placeholder = "drop here..."),
  verbatimTextOutput("droppedorder")
)


server <- function(input, output) {



  output$reactiveselect <- renderUI({
    req(input$choices)
    reactiveitems<- unlist(strsplit(input$choices,","))
    orderInput("groupstochoose", "groups to choose from:", connect='drop',items=reactiveitems)

  })

  output$droppedorder<-
    renderPrint({input$drop_order})

}



shinyApp(ui, server)

Upvotes: 1

Related Questions