6

How can I clean the "input" (the verbatimTextOutput("summary") in the example bellow) after removing some element. I tried some thing using shiny.unbindAll without succes. the dedicated removeUI doesnt do the job. Please have a look to this example :

library(shiny)

ui <- fluidPage(

    actionButton('insertBtn', 'Insert'), 
    actionButton('removeBtn', 'Remove'), 
    verbatimTextOutput("summary"),
    tags$div(id = 'placeholder') 

)

server <- function(input, output, session) {
  ## keep track of elements inserted and not yet removed
  inserted <- c()

  observeEvent(input$insertBtn, {
    btn <- input$insertBtn
    id <- paste0('txt', btn)
    insertUI(
      selector = '#placeholder',
      ## wrap element in a div with id for ease of removal
      ui = tags$div(
        actionButton(inputId = paste0("truc",id),label = paste0("truc",id)), 
        id = id
      )
    )
    inserted <<- c(id, inserted)
  })

  observeEvent(input$removeBtn, {
    removeUI(
      ## pass in appropriate div id
      selector = paste0('#', inserted[length(inserted)])
    )
    inserted <<- inserted[-length(inserted)]
  })


  output$summary <- renderPrint({
    invalidateLater(1000)
    lst <- reactiveValuesToList(input) 
    message("upd")
    lst[order(names(lst))]
  })
}

shinyApp(ui, server)

Any idea how to do this ?

Vincent Guyader
  • 2,927
  • 1
  • 26
  • 43

2 Answers2

4

You can use shinyjs to modify inputs. Would something like this work?

library(shiny)
library(shinyjs)

ui <- fluidPage(

  actionButton('insertBtn', 'Insert'), 
  actionButton('removeBtn', 'Remove'), 
  verbatimTextOutput("summary"),
  tags$div(id = 'placeholder'), 
  useShinyjs()

)

server <- function(input, output, session) {
  ## keep track of elements inserted and not yet removed
  inserted <- c()

  observeEvent(input$insertBtn, {
    btn <- input$insertBtn
    id <- paste0('txt', btn)
    insertUI(
      selector = '#placeholder',
      ## wrap element in a div with id for ease of removal
      ui = tags$div(
        actionButton(inputId = paste0("truc",id),label = paste0("truc",id)), 
        id = id
      )
    )
    inserted <<- c(id, inserted)
  })

  observeEvent(input$removeBtn, {
    id <- inserted[length(inserted)]
    removeUI(
      ## pass in appropriate div id
      selector = paste0('#',id)
    )
    #use the javascript functio Shiny.onInputChange to set the values of 
    # the removed inputs to NULL, javascript uses lower case for null
    runjs(paste0("Shiny.onInputChange('",paste0("truc",id),"',null)"))
    inserted <<- inserted[-length(inserted)]
  })


  output$summary <- renderPrint({
    invalidateLater(1000)
    lst <- reactiveValuesToList(input) 
    message("upd")
    lst[order(names(lst))]
  })
}

shinyApp(ui, server)

Hope this helps!!

Bertil Baron
  • 4,923
  • 1
  • 15
  • 24
  • 1
    I use this kind of code : `glue::glue("Shiny.onInputChange('{inp}',null)",inp=session$ns(names(reactiveValuesToList(input)))) %>%walk(runjs)` it does the job. thanks ! – Vincent Guyader Jun 26 '18 at 07:16
1

If you absolutely want to remove inputs you have created, my solution won't help (you could still use Bertil Baron's solution though). However, if you just want to clean the inputs (without removing them), then this what I would suggest :

library(shiny)

ui <- fluidPage(

  actionButton('insertBtn', 'Insert'), 
  actionButton('removeBtn', 'Remove'), 
  verbatimTextOutput("summary"),
  tags$div(id = 'placeholder') 

)

server <- function(input, output, session) {
  ## keep track of elements inserted and not yet removed
  inserted <- reactiveVal(0)

  observeEvent(input$insertBtn, {
    inserted(inserted() + 1)
    id <- paste0('txt', inserted())
    insertUI(
      selector = '#placeholder',
      ## wrap element in a div with id for ease of removal
      ui = tags$div(
        actionButton(inputId = paste0("truc", id), label = paste0("truc", id)), 
        id = id
      )
    )
  })

  observeEvent(input$removeBtn, {
    removeUI(
      ## pass in appropriate div id
      selector = paste0('#txt', inserted())
    )
    inserted(inserted() - 1)
  })


  output$summary <- renderPrint({
    invalidateLater(1000)
    lst <- isolate(reactiveValuesToList(input) )
    message("upd")
    lst[order(names(lst))]
  })
}

shinyApp(ui, server)
denrou
  • 630
  • 3
  • 12