img - GUI automática que genera en R Shiny
tags$style shiny (2)
El problema que tengo es que no puedo generar automáticamente una GUI en Shiny. La idea es ver cuántos archivos hay y generar un conjunto de botón Imagen + para cada archivo. Creo que la solución a este problema es la solución a CUALQUIER generación de GUI en R.
Puedo hacer esto de forma estática, escribiendo el código para cada botón e imagen, pero no funciona para ponerlo en un bucle for, o para renderizar la imagen en el servidor.R y pasarla como HTML a la interfaz de usuario. R. Voy a explicar a continuación.
El código que quiero generar es:
actionButton("sug1",icon=imageOutput("sug1",width="100px",height="100px"),label="First")
Lo que me da una imagen clicable de 100x100.
He probado lo siguiente:
1) Rodeándolo con un bucle for dentro de ui.R y haciendo que la ID ("sug1") y la etiqueta sean una variable donde el último número incrementa cada bucle.
2) Acumulando el resultado y usando la función HTML () en server.R para luego mostrarlo en ui.R
output$generateImages <- renderUI({
(...)
for(...){
(...)
w <- paste(w, actionButton(paste("oc",which(dir==folders)),label=dir))
}
HTML(w)
})
y luego en ui.R en el lugar donde quiero que aparezca:
htmlOutput("generateImages")
3) Supuse que usar HTMLoutput o UIOutput debería ser útil, pero dado que el resultado HTML que genera mi código (como se ve en la fuente de la página derecha / vista) es:
<button id="sug1" type="button" class="btn action-button">
<div id="sug1" class="shiny-image-output" style="width: 100px ; height: 100px"></div>
First
</button>
No pude averiguar cómo generar esto porque no sabía cómo ni dónde insertar una referencia a una imagen.
Agradecería ayuda.
Gracias a la ayuda de Jeff en la sección de comentarios, pude obtener algo que funciona en bucle y genera elementos de UI.
Todo el truco es tener una función renderUI, que tiene un bucle for dentro, que acumula los elementos en una lista, que en mi caso es:
LL[[i]] <- list(actionButton(txt,icon=imageOutput(pp,width="100px",height="100px"),label=dir))
Esta lista debe ser devuelta por la función. Todo esto está en server.R. En ui.R uno debería escribir:
uiOutput(nameOfTheFunctionThatReturnedTheList)
Mi problema es, sin embargo, que no puedo visualizar imágenes usando el mismo ciclo ... ¿Ayuda a alguien? ;)
Mi solución a este problema es la siguiente:
- Define una función que crea el tipo de widget deseado. Dale un parámetro, un entero, y agrega ese entero al nombre del widget usando `paste0 ''.
- Define un objeto reactivo que aplica la función a un vector de enteros y devuelve el resultado como una lista usando
lapply
. - Defina un objeto de salida utilizando
renderUI
que devuelve el objeto reactivo dentro detagList
.
A continuación se muestra el código para una versión de trabajo.
ui.R
library(shiny)
shinyUI(fluidPage(
titlePanel("WidgetVector"),
sidebarLayout(
sidebarPanel(uiOutput("OnButton"),uiOutput("NumberOfWidgets")),
mainPanel(uiOutput("WidgetVectorDisplay")
)
)
))
servidor.R
library(shiny)
shinyServer(function(input, output) {
output$OnButton=renderUI({radioButtons("TurnOn",label="On/Off",choices=c("On"=1,"Off"=2),selected=2)})
output$NumberOfWidgets=renderUI({numericInput("WidgetCount",label="How many widgets?",value=1)})
makeRadioButton=function(n=1){radioButtons(paste0("Radio",n),label="Pick",choices=c("a"=1,"b"=2,"c"= 3),selected=1)}
WidgetVector=reactive({lapply(X = 1:input$WidgetCount, FUN = makeRadioButton)})
output$WidgetVectorDisplay <- renderUI({
if(is.null(input$TurnOn)){return()
} else if(input$TurnOn == 2){return()
} else tagList(WidgetVector())})
})