3
votes

The problem I have is that I am not able to automatically generate a GUI in Shiny. The idea is to see how many files there are and generate a set of Image + button for each file. I believe the solution to this problem is the solution to ANY GUI generation in R.

I am able to do this statically, writing the code for each button and image, but it doesn't work to put it in a for loop, or to render the image in the server.R and pass it as HTML to the ui.R. I will explain below.

The code I want to generate is:

actionButton("sug1",icon=imageOutput("sug1",width="100px",height="100px"),label="First")

Which gives me a 100x100 clickable image.

I have tried the following:

1) Surrounding it with a for loop inside of ui.R and making the ID("sug1") and the label a variable where the last number increments each loop.

2) Accumulating the result and using the HTML() function in server.R to later output it in ui.R

output$generateImages <- renderUI({
    (...)
    for(...){
        (...)
        w <- paste(w, actionButton(paste("oc",which(dir==folders)),label=dir))
   }
   HTML(w)
   })

and then in ui.R in the place I want it to appear:

htmlOutput("generateImages")

3) I guessed that using HTMLoutput or UIOutput should help, but given that the HTML output my code generates(as seen in righ tlick/view page source) is:

<button id="sug1" type="button" class="btn action-button">
<div id="sug1" class="shiny-image-output" style="width: 100px ; height: 100px"></div>
First
</button>

I was not able to figure out how to generate this as I knew not how and where to insert a reference to an image.

Would appreciate help.

2
I think you want tagList, and possible renderUI. If you take a minute to familiarize yourself with the apply family of functions, I expect you could probably get it working with tagList(lapply( <your code here>)). - Jeff Allen
How do I later connect it with "listeners"? Any idea where I could get some more help, as nobody seems to have responded on stackoverflow! :( - user3507046
Try the mailing list: groups.google.com/forum/?fromgroups=#!forum/shiny-discuss and check out the articles on shiny.rstudio.com - Jeff Allen
Thanks Jeff! I will check out the links! So far I have seen the advanced examples of shiny and it seems none of them has the thing I am trying to do. Duh... - user3507046
Hey, I have looked through the tutorial and posted on the mailing list, but found no such example, neither was it ever explained in the tutorial how to surround a renderImage, or renderUI with a for loop, and how to later recieve such parameters also in af or loop, or anything similar. Everything there was only showing how to put an image statically, and not how to generate UIs dynamically :(. I am totally lost. - user3507046

2 Answers

0
votes

Thanks to the help of Jeff in the comment section, I was able to get something that loops and generates elements of UI.

The whole trick is to have a renderUI function, that has a for loop inside, which accumulates the elements in a list, which in my case is:

LL[[i]] <- list(actionButton(txt,icon=imageOutput(pp,width="100px",height="100px"),label=dir))

This list has to be returned by the function. All this is in server.R. In ui.R one should write:

uiOutput(nameOfTheFunctionThatReturnedTheList)

My problem still is however that I cannot make it to display images using the same loop...Help anyone? ;)

0
votes

My solution to this problem is as follows:

  1. Define a function that creates the desired type of widget. Give it one parameter, an integer, and append that integer to the name of the widget using `paste0'.
  2. Define a reactive object that applies the function to a vector of integers and returns the result as a list using lapply.
  3. Define an output object using renderUI that returns the reactive object inside tagList.

Below is the code for a working version.

ui.R

library(shiny)
shinyUI(fluidPage(
  titlePanel("WidgetVector"),
  sidebarLayout(
    sidebarPanel(uiOutput("OnButton"),uiOutput("NumberOfWidgets")),
    mainPanel(uiOutput("WidgetVectorDisplay")
    )
  )
))

server.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())})
})