es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Hay alguna forma de crear una función envolvente para renderUI en Shiny (R)?

Necesito usar renderUI para crear múltiples opciones de entrada basadas en el valor de otra entrada. Quiero envolver todo dentro de renderUI como una función para poder aplicar esto a muchas entradas similares. Aquí hay un ejemplo simplificado (que funciona para mí, pero no quiero repetir la parte de renderUI muchas veces, porque tengo muchas otras entradas como i1):

library(shiny)
ui <- fluidPage(
    fluidRow(
        selectInput(
            inputId = 'i1',
            label = 'choice 1',
            choices = list(5, 10)
        ),
        uiOutput('o1')
    )
)
server <- function(input, output, session) {
    output$o1 <- renderUI(
        fluidRow(
            sliderInput(
                inputId = 's1',
                label = 'slider 1',
                min = 0, max = as.numeric(input$i1) * 10,
                value = 0.5
            ),
            sliderInput(
                inputId = 's2',
                label = 'slider 2',
                min = 0, max = as.numeric(input$i1) * 100,
                value = 0.5
            )
        )
    )
}
shinyApp(ui = ui, server = server)

El problema es que cuando intenté envolverlo en una función, la salida creada por renderUI deja de actualizarse cuando cambio el valor de entrada. Aquí está el código que no funciona para mí:

library(shiny)
renderUI_warpper <- function(i){
    renderUI(
        fluidRow(
            sliderInput(
                inputId = 's1',
                label = 'slider 1',
                min = 0, max = as.numeric(i) * 10,
                value = 0.5
            ),
            sliderInput(
                inputId = 's2',
                label = 'slider 2',
                min = 0, max = as.numeric(i) * 100,
                value = 0.5
            )
        )
    )
}
ui <- fluidPage(
    fluidRow(
        selectInput(
            inputId = 'i1',
            label = 'choice 1',
            choices = list(5, 10)
        ),
        uiOutput('o1')
    )
)
server <- function(input, output, session) {
    output$o1 <- renderUI_warpper(input$i1)
}
shinyApp(ui = ui, server = server)
Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema con el código actualizado es que renderUI_wrapper solo se ejecuta una vez cuando se crea la salida por primera vez, y no se vuelve a ejecutar cuando cambia el valor de entrada. Para que funcione, necesitamos envolver la llamada a la función en una expresión reactive, que volverá a ejecutar la función siempre que cambie el valor de entrada. Aquí está el código modificado que debería funcionar:

    library(shiny)
    
    renderUI_wrapper <- function(i){
      fluidRow(
        sliderInput(
          inputId = 's1',
          label = 'slider 1',
          min = 0, max = as.numeric(i) * 10,
          value = 0.5
        ),
        sliderInput(
          inputId = 's2',
          label = 'slider 2',
          min = 0, max = as.numeric(i) * 100,
          value = 0.5
        )
      )
    }
    
    ui <- fluidPage(
      fluidRow(
        selectInput(
          inputId = 'i1',
          label = 'choice 1',
          choices = list(5, 10)
        ),
        uiOutput('o1')
      )
    )
    
    server <- function(input, output, session) {
      output$o1 <- renderUI({
        renderUI_wrapper(input$i1)
      })
    }
    
    shinyApp(ui = ui, server = server)
    

    En este código modificado, hemos eliminado la función renderUI de la función renderUI_wrapper y, en su lugar, la estamos llamando dentro de la función renderUI de la salida. Además, hemos envuelto la llamada a la función renderUI_wrapper dentro de una expresión reactive, para que se vuelva a ejecutar siempre que cambie el valor de entrada.

Comments are closed.