acircleda
acircleda

Reputation: 759

Clear data when removeUI used

I am using observeEvent to insert a UI (in the example below, it adds an additional numeric input box) with insertUI and likewise observeEvent to remove those UIs via removeUI. The issue is that the data that is created through those UIs does not clear or reset. In the example below, you can enter numbers in separate numeric input boxes and press Go! to sum them together. Upon removing elements, it should clear our that data and re-sum, but it keeps the last number added.

For example, if 1 is in the first box and two more input boxes are added, both with 1s, pressing Go! correctly sums them to 3. However, removing the two text boxes and pressing Go! keeps 3 when it should just show 1.

I am sure I have missed something simple. My reprex is below:

library(shiny)

ui <- fluidPage(

    # Application title
    titlePanel("example"),

    # button input
    sidebarLayout(
        sidebarPanel(
            numericInput(
                "number",
                "A Number 1-10",
                1,
                min = 1,
                max = 10,
                step = NA,
                width = NULL),
            #add/remove buttons
            fluidRow(column(
                6,
                actionButton('insertBtn', 'Add Number'), 
                actionButton('removeBtn', 'Remove Number'), 
                tags$div(id = 'placeholder') 
            )),
            # go button
            fluidRow(column(
                6, actionButton(inputId = "go", label = "Go!"),
            ))
        ),

        # output
        mainPanel(
            htmlOutput("total")
        )
    )
)

server <- function(input, output) {
    
    # add text boxes when clicked
    
    inserted <- c()
    
    observeEvent(input$insertBtn, {

    btn <- input$insertBtn
    id <- paste0('number', btn)
    insertUI(
        selector = '#placeholder',
        ## wrap element in a div with id for ease of removal
        ui = tags$div(
            fluidRow(
                numericInput(
                   id,
                    "A Number 1-10",
                    1,
                    min = 1,
                    max = 10,
                    step = NA,
                    width = NULL)
            ),
            id = id)
    )
    inserted <<- c(id, inserted)
})

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

# add numbers in boxes

final_number_text <- eventReactive(input$go, {
    
    
    btn <- input$insertBtn
    if(btn > 0){
        
        total <- input$number
        
        for(i in 1:btn){
            
            total<- total+ (input[[paste0("number", i)]])
        }
        
        
    } else {
        
        total <- input$number
        
    }
    
    HTML(paste(total))
})

output$total <- renderText({
    final_number_text()
})

}

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

Upvotes: 0

Views: 56

Answers (2)

YBS
YBS

Reputation: 21297

Please note that when you remove a number, you are not decreasing the value of input$insertBtn. Therefore, you want to count only the elements that are in inserted. Therefore, replace

for(i in 1:btn){...}

with

lapply(inserted, function(par) {total <<- total + input[[par]]})

  

Full code

library(shiny)

ui <- fluidPage(

  # Application title
  titlePanel("example"),

  # button input
  sidebarLayout(
    sidebarPanel(
      numericInput(
        "number",
        "A Number 1-10",
        1,
        min = 1,
        max = 10,
        step = NA,
        width = NULL),
      #add/remove buttons
      fluidRow(column(
        6,
        actionButton('insertBtn', 'Add Number'),
        actionButton('removeBtn', 'Remove Number'),
        tags$div(id = 'placeholder')
      )),
      # go button
      fluidRow(column(
        6, actionButton(inputId = "go", label = "Go!"),
      ))
    ),

    # output
    mainPanel(
      htmlOutput("total")
    )
  )
)

server <- function(input, output, session) {

  # add text boxes when clicked

  inserted <- c()

  observeEvent(input$insertBtn, {

    btn <- input$insertBtn
    id <- paste0('number', btn)
    insertUI(
      selector = '#placeholder',
      ## wrap element in a div with id for ease of removal
      ui = tags$div(
        fluidRow(
          numericInput(
            id,
            "A Number 1-10",
            1,
            min = 1,
            max = 10,
            step = NA,
            width = NULL)
        ),
        id = id)
    )
    # inserted <<- c(id, inserted) ##  removes first one first
    inserted <<- c(inserted, id)   ##  removes last one first
  })

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

  # add numbers in boxes
  final_number_text <- eventReactive(input$go, {

    total <- input$number
    if(length(inserted) > 0){
      lapply(inserted, function(par) {total <<- total + input[[par]]})
    }

    HTML(paste(total))
  })

  output$total <- renderText({
    final_number_text()
  })

}

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

Upvotes: 1

akrun
akrun

Reputation: 887098

We may need seq_along which would be bug free when the length is 0

for(i in seq_along(inserted)) {...}

Upvotes: 1

Related Questions