1
votes

I'm pretty new at this so forgive me - I'm building an app in Shiny that takes an uploaded data file of a fixed format, and renders out various plots based on user selections. One important part of the app is a set of tabs which each contain one plot.

I'm using renderUI to render the tabs but I'm having a bunch of difficulty rendering the plot. I've tried renderPlot, outputPlot and can't get the plot to show. I get various errors but the code below is generating "Error in as.character(x) : cannot coerce type 'closure' to vector of type 'character'" at the point where we renderPlot(engPlot).

ui.R

# Define UI
shinyUI(fluidPage(
# Application title
  titlePanel("Chart Creation Tool"),
# Sidebar
sidebarLayout(
   sidebarPanel(
      fileInput("fileBlob", "Upload File", multiple = FALSE, accept = NULL),
      selectInput("selectAnalysis", label=h3("Select Input"), choices=c("Month x Year", "Strategies", "Programs", "Segments")),
   uiOutput("strategyList")
),

# Show a plot of the generated distribution
mainPanel(
  uiOutput("mainPanel")      
)
)
))

mainPanel portion of server.R

output$mainPanel <- renderUI ({

if (length(RawImport())==0L) {

  out <- NULL

}else{
  if (input$selectAnalysis=="Month x Year") {
    dfAggMonth <- aggregate(cbind(Sent,Delivered,UniqueOpens,Responders,Bounced,Unsubscribes,TotalSpamComplaints,HardBounces,SoftBounces) ~ SentMonth + SentYear + SentMonthName, RawImport(), FUN = sum)
    dfAggMonth <- addRatios(dfAggMonth)
    dfAggMonth <- dfAggMonth[with(dfAggMonth, order(Date)), ]

    engPlot <- runplot(paste(dfAggMonth$SentMonthName, dfAggMonth$SentYear,sep="-"), dfAggMonth$Date, dfAggMonth$Delivered, dfAggMonth$UniqueOpenRate, dfAggMonth$ResponderRate, "engagement", , "Temp Title")

    out <- tabsetPanel(
      tabPanel("Engagement", "Engagement", renderPlot(engPlot)), 
      tabPanel("Summary", "summary", "summary"),
      tabPanel("Deliverability",runplot(paste(dfAggMonth$SentMonthName, dfAggMonth$SentYear,sep="-"), dfAggMonth$Date, dfAggMonth$Delivered, dfAggMonth$BounceRate, , "deliverability", , "Temp Title"))
      )  
  }
  else {
    out <- tabsetPanel(
      tabPanel("Tab 1", input$selectAnalysis), 
      tabPanel("Tab 2", input$selectAnalysis)
    )
  }

}

out
})

RunPlot Function

runplot <- function(xSeriesLabels, xSeriesValues, leftseries, rightseries1, rightseries2, chartType, columnSeries, xTitle){

if (missing(xTitle)==FALSE) {
   strTitle <- xTitle
  } else {
    strTitle <- "no title supplied"
  }


  p <- barplot(leftseries, width=1, col=barCol, axisnames = leftseries, names.arg=xSeriesLabels, axis.lty=1, xlab=strTitle)

  return(p)
}
1

1 Answers

2
votes

I've found this error often occurs when you're running a function that's meant to be run in server.R in ui.R.

So you'll have to remember that renderUI is going to create a full-fledged client-side UI. That means that any code you're returning in your dynamic UI (even though it happens to be stored in server.R must really be valid client-side code that could exist in ui.R. That also means that testing can be much easier in that you can just move the code you're trying to create dynamically (such as one of the out tabsetPanels) to your ui.R to see if it works. That may make debugging easier in the future.

In this case, I think the problem you'd see if you did that is around the renderPlot call. Since you're just creating a dynamic UI here, you want to use the UI-compatible functions, which is plotOutput("plotName"), in this case. Then on the server side you'll assign a plot to that output.

output$plotName <- renderPlot({
 ...
})

Which will do what you want when the plot is visible, and will have no visible effect when the plot isn't shown.