How to DRY many outputs?

229 views
Skip to first unread message

Alberto Santini

unread,
Mar 25, 2013, 9:15:47 AM3/25/13
to shiny-...@googlegroups.com

Hello.

I need to display a lot of outputs. 

For instance,

    output$fooA1 <- renderText({...
    output$fooB1 <- renderText({...
    output$fooC1 <- renderText({...

    output$fooA2 <- renderText({...
    output$fooB2 <- renderText({...
    output$fooC2 <- renderText({...

and so on.

The content of 'fooA1' and 'fooA2' expressions call different reactive functions, because the inputs are different, but they follow a similar pattern.

How to refactor the output rendering without repeating the code?

Pseudo code:
createFooOutput("output$fooA1", "getFoo(input$A1)")
createFooOutput("output$fooB1", "getFoo(input$B1)")
...

Thanks in advance,
Alberto

Winston Chang

unread,
Mar 25, 2013, 12:07:02 PM3/25/13
to shiny-...@googlegroups.com
You can use double-bracket indexing on input and output, so you should be able to do something like this:

input_names <- c('A1', 'B1', 'C1')

for (in_name in input_names) {
  out_name <- paste('foo', in_name, sep = '')

  output[[out_name]] <- renderText({ ... input[[in_name]] ... })
}



--
You received this message because you are subscribed to the Google Groups "Shiny - Web Framework for R" group.
To unsubscribe from this group and stop receiving emails from it, send an email to shiny-discus...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Joe Cheng

unread,
Mar 25, 2013, 12:55:27 PM3/25/13
to shiny-...@googlegroups.com
You also need to add another variable scope (local()) so that in_name is not shared between all the different renderText calls (this is an R thing, not a Shiny thing):

input_names <- c('A1', 'B1', 'C1')

for (in_name in input_names) {
  local({
    my_in_name <- in_name
    out_name <- paste('foo', my_in_name, sep = '')

    output[[out_name]] <<- renderText({ ... input[[my_in_name]] ... })
  })
}

Alberto Santini

unread,
Mar 25, 2013, 3:40:53 PM3/25/13
to shiny-...@googlegroups.com
Hello Winston, Joe.


On Monday, March 25, 2013 5:55:27 PM UTC+1, Joe Cheng [RStudio] wrote:
You also need to add another variable scope (local()) so that in_name is not shared between all the different renderText calls (this is an R thing, not a Shiny thing):


Thanks for the great suggestion: double-bracket indexing and local do the job.

The final code:

    output_names <- c(
        "profileA1",
        "profileB1",
        "profileA2",
        "profileB2",
        "profileA3",
        "profileB3",
        "profileA4",
        "profileB4"
    )
    reactive_names <- c(
        "game1PlayerAProfile",
        "game1PlayerBProfile",
        "game2PlayerAProfile",
        "game2PlayerBProfile",
        "game3PlayerAProfile",
        "game3PlayerBProfile",
        "game4PlayerAProfile",
        "game4PlayerBProfile"
    )

    for (out_name in output_names) {
        local({
            my_out_name <- out_name
            info_names <- c("Card", "Player", "Rating")
            for (info_name in info_names) {
                local({
                    my_info_name <- info_name
                    complete_out_name <- paste(my_out_name, my_info_name, sep = "")

                    output[[complete_out_name]] <<- renderText({
                        my_profile <- get(reactive_names[which(output_names == my_out_name)])()
                        my_profile[[tolower(my_info_name)]]
                    })
                })
            }
        })
    }

Regards,
Alberto


Reply all
Reply to author
Forward
0 new messages