rstudio / sortable

R htmlwidget for Sortable.js
https://rstudio.github.io/sortable/
Other
131 stars 29 forks source link

Updating UI elements selection in sortable rank list #79

Closed GreyMerchant closed 2 years ago

GreyMerchant commented 2 years ago

Hi!

I am hoping someone can help me with my shiny question/problem below. You will see that we basic have 2 sets. We have a change_radio which when clicked changes the selection made in rb based on a updateSelectInput.

I want to do exactly the same thing but for a rank_list from the sortable package. When you click on change_bucket it should update the selection in the end_bucket. So lets say if clicked it should automatically add "ccc" to that bucket.

I looked at the documentation for sortable but didn't find a similar function like updateSelectInput. Any idea how I would go about doing this?


library(shiny)
library(sortable)

ui <- fluidPage(

  splitLayout(
  radioButtons("rb", "Choose one:",
               choiceNames = list(
                 icon("calendar"),
                 HTML("<p style='color:red;'>Red Text</p>"),
                 "Normal text"
               ),
               choiceValues = list(
                 "icon", "html", "text"
               ),
               selected = "text"
               ),
  textOutput("txt"),
  actionButton("change_radio","Change radio button selection")
),
bucket_list(
  header = "This is a bucket list. You can drag items between the lists.",
  add_rank_list(
    input_id = "start_bucket",
    text = "Drag from here",
    labels = c("a", "bb", "ccc")
  ),
  add_rank_list(
    input_id = "end_bucket",
    text = "to here",
    labels = NULL
  )
),

actionButton("change_bucket", "Change bucket selection")
)

server <- function(input, output, session) {
  output$txt <- renderText({
    paste("You chose", input$rb)
  })

  observeEvent(input$change_radio,{
    updateSelectInput(session, "rb", selected = "html")

  })

  observeEvent(input$change_bucket,{
    # browser()
    # updateSelectizeInput(session,"end_bucket",choices = c("a"), label = c("a"))
    # 
    # 
    # updateSelectInput(session,"end_bucket",choices = c("a"), label = c("a"))
  })

}

shinyApp(ui, server)
andrie commented 2 years ago

I think the vignette at https://rstudio.github.io/sortable/articles/updating_rank_list.html has an example of how to do this.

The mental model here is that a rank_list() or a bucket_list() are not reactive objects themselves, so you can't update these using updateSelect() or updateSelectize() (they are not select inputs).

Instead, you have to update the underlying data in the lists that you pass to rank_list() or bucket_list() and the way to do that is to use renderUI().

HTH

GreyMerchant commented 2 years ago

I tried doing that but my rank list is at a very peculiar position in this application where if I try and throw a renderUI() call around it I get object of type 'closure' is not subsettable.

Is there some way this can be accomplished with something like session$sendCustomMessage ?

andrie commented 2 years ago

Here you go.


library(shiny)
library(sortable)

ui <- fluidPage(

  splitLayout(
    radioButtons("rb", "Choose one:",
                 choiceNames = list(
                   icon("calendar"),
                   HTML("<p style='color:red;'>Red Text</p>"),
                   "Normal text"
                 ),
                 choiceValues = list(
                   "icon", "html", "text"
                 ),
                 selected = "text"
    ),
    textOutput("txt"),
    actionButton("change_radio","Change radio button selection")
  ),
  uiOutput("sortable"),
  actionButton("change_bucket", "Change bucket selection")
)

server <- function(input, output, session) {
  output$txt <- renderText({
    paste("You chose", input$rb)
  })

  rv <- reactiveValues(
    labels_start = c("a", "bb", "ccc"),
    labels_end = NULL
  )

  output$sortable <- renderUI({
    bucket_list(
      header = "This is a bucket list. You can drag items between the lists.",
      add_rank_list(
        input_id = "start_bucket",
        text = "Drag from here",
        labels = rv$labels_start
      ),
      add_rank_list(
        input_id = "end_bucket",
        text = "to here",
        labels = rv$labels_end
      )
    )

  })

  observeEvent(input$change_radio,{
    updateSelectInput(session, "rb", selected = "html")

  })

  observeEvent(input$change_bucket,{
    rv$labels_start <- setdiff(input$start_bucket, "ccc")
    rv$labels_end <- c(setdiff(input$end_bucket, "ccc"), "ccc")
  })

}

shinyApp(ui, server)