0

What I'm trying to do is pass a value (the choice encapsulated in a radio button) of one module to another (which takes the choice and spits out a graph appropriate to it).

I've read a lot about reactive() and related functions, and still don't really know how to use the function appropriately. It seems to me that one should only have to call reactive() once, when declaring something—and that something will be reactive through out it's whole usage. This doesn't seem to be the case, though:

server function of first module:

# Return the choice user selects
sidePanel <- function(input, output, session) {
    selected_graph <- reactive({input$selected_graph})
    return(selected_graph)
}

server function of second module:

source('graph_choices.R')
mainPanel <- function(input, output, session, data, choice) {
        output$graph <- renderPlot({
            match.fun(reactive(choice))(data)
        })
}

graph_choices.R

choice_1 <- function(data) {
ggplot(data, aes(x=time, y=score)) + geom_point()

choice_2 <- function(data) {
ggplot(data, aes(x=eyelashes, y=score)) + geom_bar(stat='identity')

server function of app

server <- function(input, output, session) {
    file_name <- parseQueryString(isolate(session$clientData$url_search))
    sounds <- read.csv(paste('/srv/tmp_data/', file_name, sep=""), encoding='UTF-8')
    sounds_trimmed <- filter(sounds, score != -1)
    sidePanel <- callModule(sidePanel, "side")
    mainPanel <- callModule(mainPanel, "main", data=sounds_trimmed, choice=sidePanel())
}

So, what's going on here is that the first module sets up the side-panel with two radio buttons—one whose value is choice_1 and one whose value is choice_2. Upon selecting the button, the return bit spits out the choice, and it's passed to the server function of the second module, which spits out the appropriate graph.

I know that my problem is in my usage of reactive() because, without it, everything "works" well (the first radio button is selected by default, that choice is given to the second module, and the appropriate graph is shown.) But, when I change the radio button, nothing happens.

I've a bunch of different permutations on where to put reactive, and get different results sometimes (once I enclosed the second module's output with reactive() and seemed like something changed, but still nothing updated).

Would anyone mind helping me out?


I've also tried mainPanel <- callModule(mainPanel, "main", data=sounds_trimmed, selected_graph=sidePanel) with match.fun(selected_graph())(data) as per this question; the graph prints out (as before, but doesn't change upon changing the button).

AmagicalFishy
  • 1,249
  • 1
  • 12
  • 36
  • I think you may have more luck if you provide a reproducible example (a minimal example of your ui+server that can be run). You have a lot of information here that's quite hard for me to follow. – Chris Aug 21 '18 at 15:26

1 Answers1

0

I had to make some guesses in order to come up with an app that hopefully illustrates how to solve your problem. I renamed mainPanel to mP to not avoid name collusions with shiny::mainPanel (probably irrelevant).

The key is to map from the choice given via selectInput to the plotting function which I did with

plotFun <- switch(choice(), choice_1 = choice_1, 
                  choice_2 = choice_2, stop("invalid choice()"))

I prefer to use explicit mapping and really don't see a lot of cases where functions like base::get are required.

About the usage of reactive: You want to make sure that all "dynamic" inputs and outputs for/from your module are created with shiny::reactive. Then you evaluate them after passing. There are other ways to pass "dynamic" objects, but this is the recommended way given all the documentation I saw about modules so far.

library(shiny)

choice_1 <- function(data) 
  plot(factor("choice 1"))
choice_2 <- function(data) 
  plot(factor("choice 2"))

sidePanelUI <- function(id) {selectInput(NS(id, "selected_graph"), "graph", 
                                         c("choice_1", "choice_2"))}  
sidePanel <- function(input, output, session) {
  reactive({input$selected_graph})
}

mPUI <- function(id) {
  plotOutput(NS(id, "graph"))
}
mP <- function(input, output, session, data, choice) {
  output$graph <- renderPlot({
    plotFun <- switch(choice(), choice_1 = choice_1, 
                      choice_2 = choice_2, stop("invalid choice()"))
    plotFun(data)
  })
}

ui <- fluidPage(
  sidePanelUI("side"),
  mPUI("main")
)

server <- function(input, output) {
  sidePanel <- callModule(sidePanel, "side")
  callModule(mP, "main", data = mtcars, choice = sidePanel)
}

shinyApp(ui, server)
Gregor de Cillia
  • 7,397
  • 1
  • 26
  • 43