Показать / скрыть входы на основе numericInput и actionButton

В блестящем приложении есть следующие элементы:

  • одно поле numericInput со значениями от 0 до 3
  • один uiOutput, содержащий три скрытых textInput поля
  • один actionButton

Я хотел бы добиться show скрытых textInput полей после нажатия кнопки. Количество отображаемых полей зависит от числа, выбранного в numericInput. Полнофункциональный код ниже успешно справляется с этим; однако есть проблема, решения которой я не могу найти. Например, если я выберу 3 и нажму кнопку, появятся 3 скрытых поля textInput (ура!), Но если я сразу выберу число меньше 3 и нажму кнопку, нежелательные поля все равно останутся. Как я могу этого добиться? Спасибо

library(shiny)
library(shinyjs)

ui <- fluidPage(

  useShinyjs(),

  numericInput(inputId = "num", label = "How many inputs do you want to show?", value = 1, min = 1, max = 3),

  uiOutput(outputId = "out"),

  actionButton(inputId = "go", label = "Click me!")
)

server <- function(input, output){

  output$out <- renderUI({
    numinputs <- lapply(1:3, function(i){
      textInput(inputId = paste0("txt", i), label = paste0("Text input ", i))
    })
    shinyjs::hidden(numinputs)
  })

  observeEvent(eventExpr = input$go, handlerExpr = {
    for(i in seq(input$num)){
      shinyjs::show(id = paste0("txt", i))
    }
  })
}

shinyApp(ui = ui, server = server)

person SavedByJESUS    schedule 18.11.2016    source источник


Ответы (2)


Этот код похож на код @SBista, но без переменной nout.

library(shiny)
library(shinyjs)

ui <- fluidPage(
    
    useShinyjs(),
    
    numericInput(inputId = "num", label = "How many inputs do you want to show?", value = 1, min = 1, max = 3),
    
    uiOutput(outputId = "out"),
    
    actionButton(inputId = "go", label = "Click me!")
)

server <- function(input, output){
    output$out <- renderUI({
        numinputs <- lapply(1:3, function(i){
            textInput(inputId = paste0("txt", i), label = paste0("Text input ", i))
        })
        shinyjs::hidden(numinputs)
    })
    
    observeEvent(eventExpr = input$go, handlerExpr = {
        n <- seq(length.out = as.numeric(input$num))
        lapply(seq(3), function(i) {
            if(i %in% n) {
                shinyjs::show(id = paste0("txt", i))
            } else{
                shinyjs::hide(id = paste0("txt", i))
            }
        })
    })
}

shinyApp(ui = ui, server = server)

#edit - без shinyjs / динамического создания

# if you comment the lines marked with # no-button
# the app will change the number of textInputs as soon as you change the numericInput
library(shiny)

ui <- fluidPage(
    numericInput(inputId = "num", label = "How many inputs do you want to show?", value = 1, min = 1, max = 3),
    uiOutput(outputId = "out"),
    actionButton(inputId = "go", label = "Click me!") # no-button
)

server <- function(input, output){
    output$out <- renderUI({
        input$go # no-button
        isolate( # no-button
            numinputs <- lapply(seq(length.out = req(input$num)), function(i){
                textInput(inputId = paste0("txt", i), label = paste0("Text input ", i))
            })
        ) # no-button
    })
}

shinyApp(ui = ui, server = server)
person user5029763    schedule 18.11.2016
comment
Я очень ценю помощь. - person SavedByJESUS; 18.11.2016
comment
Я особо не объяснил в своем ответе. Вы поняли, что мы там делали? hidden() инициализирует только textInput() как невидимый объект. show() и hide() - это те, которые реагируют на пользователя. - person user5029763; 18.11.2016
comment
Я хорошо понял. Что я не смог понять (до вашего ответа), так это то, как вы настроили переменную n и цикл lapply. Очень умно сделано! - person SavedByJESUS; 18.11.2016
comment
Я только что понял, что, возможно, вам не нужно использовать shinyjs. Вы можете динамически создавать textInputs по мере необходимости. Я отредактирую свой ответ и добавлю другой вариант. - person user5029763; 18.11.2016
comment
С conditionPanel()? - person SavedByJESUS; 18.11.2016
comment
Поскольку вы уже создаете textInput на стороне сервера, вы можете создавать их по мере необходимости вместо того, чтобы создавать их все сразу, а затем скрывать их. - person user5029763; 18.11.2016
comment
Это правда. Большое тебе спасибо. - person SavedByJESUS; 18.11.2016
comment
Я только что видел правку. Еще раз большое спасибо. Я не знал о функции req. Я изучу код, чтобы понять его. - person SavedByJESUS; 21.11.2016

Я изменил ваш код, чтобы делать именно то, что вы хотели.

library(shiny)
library(shinyjs)

ui <- fluidPage(

  useShinyjs(),

  numericInput(inputId = "num", label = "How many inputs do you want to show?", value = 1, min = 1, max = 3),

  uiOutput(outputId = "out"),

  actionButton(inputId = "go", label = "Click me!")
)

server <- function(input, output){
  nout <- 0

  output$out <- renderUI({
    numinputs <- lapply(1:3, function(i){
      textInput(inputId = paste0("txt", i), label = paste0("Text input ", i))
    })
    shinyjs::hidden(numinputs)
  })

  observeEvent(eventExpr = input$go, handlerExpr = {


      if(nout > input$num){ # If the current no. of inputs is less than previous hide the inputs
        for(i in nout:(nout-as.numeric(input$num))){
          shinyjs::hide(id = paste0("txt", i)) 
        } 

      }else{
        for(i in seq(input$num)){
        shinyjs::show(id = paste0("txt", i)) 
      }

    }

    nout <<- input$num
  })
}

shinyApp(ui = ui, server = server)

Надеюсь, это поможет!

person SBista    schedule 18.11.2016
comment
Это очень помогает. Большое тебе спасибо. - person SavedByJESUS; 18.11.2016
comment
@SavedByJESUS ​​Не могли бы вы принять ответ, если он вам помог? - person SBista; 18.10.2017