shiny renderGvis object output not found - shiny

I can't bring a minimal example since it works for one code but not for this one I am asking about. I try to explain the structure of the code because I am pretty sure that someone can help me.
I have the usual Server.R file with
Server <- function(input, output, session) {
source("ChartServer.R")
}
where source("ChartServer.R"):
output$ChartPlotOutput <- renderGvis({
gvisChart <- CREATES A CHART
return(gvisChart)
})
and the ui.R file which is a dasboardpage:
source("servicefunctions.R")
source("dashboardBody.R")
source("dashboardHeader.R")
source("dashboardSidebar.R")
dashboardPage(
dashboardHeader,
dashboardSidebar,
dashboardBody
)
I have three tab Items of which two are working fine. However one tries to render a plot which is not working (the one mentioned in the server.R file above)
source("ChartUI.R")
aboutTab2 <- tabItem(tabName = "about2",
fluidPage(
fluidRow(
tabBox(id = "PChartUI", width = 7,
tabPanel(title = 'Prices', PChartUI)
))))
source("ChartUI.R"):
PChartUI <- tagList(
htmlOutput("ChartPlotOutput"),
imageOutput("ChartPlotWidthPlaceholder",width = '100%', height = '50px'))
when I try to run this app i always get the error:
Error in output$ChartPlotOutput <- renderGvis({ :
object 'output' not found
As mentioned I already worked with a similar structure that worked but here I can't find what I did wrong.
Thanks a lot

Related

Shiny: Getting a user input into a future function

I am building an shiny app, where users upload a bunch of data and than choose which should be computed. The computation itself is rather timeconsuming and should be stored in a list. To keep shiny responsive during the calculation (for the user and other users) I tried to utilize promises and future. The problem is that I am not able to get an input into future function. I always get Warning: Error in $: Can't access reactive value 'mem_pos' outside of reactive consumer. i Do you need to wrap inside reactive() or observe()? [No stack trace available]. I tried to read about reactive but I am simply stuck.
Here is a minimal example of the problem (to display it, the list has only one value each):
library(shiny)
library(promises)
library(future)
plan(multisession)
# example function
subfct = function(n) {
Sys.sleep(3)
return(n*2)
}
# shiny page
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
numericInput("mem_pos", min = 1, max = 30, value = 1, label="mem pos"),
actionButton("mem_button", label="set mem value")
),
mainPanel(
tableOutput("result")
)
)
)
server <- function(input, output) {
superval = reactiveValues(mem = rep(list(0), 10))
# set the future calculations
observeEvent(input$mem_button, {future({return(subfct( input$mem_pos ))}) %...>% {superval$mem[[input$mem_pos]] = .}}) # here lies the problem
# show result table
observe( {output$result = renderTable({unlist(superval$mem)})})
}
# Run the application
shinyApp(ui = ui, server = server)
If the problematic line is exchanged by observeEvent(input$mem_button, {future({return(subfct( 5 ))}) %...>% {superval$mem[[input$mem_pos]] = .}}) it basically works. But I am not able to get the user input into the function. I am grateful for a direct help or an explanation of reactive for my specific problem.
I solved it. Not enterily sure why, but isolate does the trick.
This code works for me:
library(shiny)
library(promises)
library(future)
plan(multisession)
# example function
subfct = function(n) {
Sys.sleep(3)
return(n*2)
}
# shiny page
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
numericInput("mem_pos", min = 1, max = 30, value = 1, label="mem pos"),
actionButton("mem_button", label="set mem value")
),
mainPanel(
tableOutput("result")
)
)
)
server <- function(input, output) {
superval = reactiveValues(mem = rep(list(0), 10))
# set the future calculations
observeEvent(input$mem_button, {future({return(subfct( isolate(input$mem_pos) ))}) %...>% {superval$mem[[input$mem_pos]] = .}}) # here lied the problem
# show result table
observe( {output$result = renderTable({unlist(superval$mem)})})
}
# Run the application
shinyApp(ui = ui, server = server)
You may try to use delay() function from shinyjs package. This enables the code to run only after the times set lapses. e.g.
library(shinyjs)
ui<-fluidPage(useShinyjs(),
...)
server<-function(input,output, session){
delay (ms=,
...)
}
shinyApp(ui,server)

I keep getting an error in my shiny app for linear regression?

I'm trying to create a shiny app and I can't seem to find the error in my code.
I keep getting this error here:
Error in match.arg(position) : 'arg' must be NULL or a character vector
I'm am also unsure as to what the inputs should be.
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
titlePanel("Linear Regression Shiny App"),
sidebarLayout(
sidebarPanel(
h1("Linear Regression"),
p("Select inputs for the Response
Variable"),
selectInput("ResVar",
"Response Variables:",
c("","","")
),
p("Select inputs for the Predictor
Variable"),
selectInput("PreVar",
"Predictor Variables:",
c("","","")
),
actionButton("goButton","Go!"),
plotOutput("distPlot")),
mainPanel =
verbatimTextOutput("ResVarPrint"),
verbatimTextOutput("PreVarPrint")
))
# Define server logic required to draw a histogram
server <- function(ResVar,PreVar) {
lm1 <- reactive({reformulate((input$ResVar),(input$PreVar))})
output$ResPrint <- renderPrint({input$ResVar})
output$PrePrint <- renderPrint({input$PreVar})
output$RegSum <- renderPrint({summary(lm1())})
}
# Run the application
shinyApp(ui = ui, server = server)
You had misplaced some parenthesis near the end of you UI code, and tried to use mainPanel= instead of the proper mainPanel(. The UI code below addresses the error and gets your app to load.
ui <- fluidPage(
titlePanel("Linear Regression Shiny App"),
sidebarLayout(
sidebarPanel(
h1("Linear Regression"),
p("Select inputs for the Response
Variable"),
selectInput("ResVar",
"Response Variables:",
c("","","")
),
p("Select inputs for the Predictor
Variable"),
selectInput("PreVar",
"Predictor Variables:",
c("","","")
),
actionButton("goButton","Go!"),
plotOutput("distPlot")
),
mainPanel(
verbatimTextOutput("ResVarPrint"),
verbatimTextOutput("PreVarPrint")
)
)
)
However, you may want to consider whether you actually want your plotOutput in the sidebar or whether you want it in the main panel, in which case you'll need to move it down.

Folder selection in Shiny App (locally and on the server) to read the files and save results

I am trying to use the solution proposed here.
The difference is that I want the user to chose two folders, one to save the result of my code, and one that has all files.
Now the question is that how can I save files in the second folder (input$fileout). Is there a way to pass this path to a function that processes my input files? I think there will be a permission issue.
Edit: I'd like to use dataHandler inside my.analysis() function as I need to save multiple pngs, csv and some specific formatted files. What would be the best approach? My shinyApp does not print out anything, except that analysis is done, download the result.
Here's the updated ui.R
library(shiny)
library(shinythemes)
library(shinyWidgets)
shinyUI(tagList(fluidPage(theme = shinytheme("lumen"),
includeScript("./www/text.js"),
titlePanel("Test"),
fluidRow(
column(4,
tags$div(class="form-group shiny-
input-container",
tags$div(tags$label("Choose a
folder", class="btn btn-primary",
tags$input(id = "fileIn", webkitdirectory = TRUE, type = "file", style="display: none;", onchange="pressed()"))),
tags$label("No folder choosen", id = "noFile"),
tags$div(id="fileIn_progress", class="progress progress-striped active shiny-file-input-progress",
tags$div(class="progress-bar")
)
)),
verbatimTextOutput("tbl")
),
fluidRow(
column(8,
verbatimTextOutput("results"))
)
),
HTML("<script type='text/javascript' src='getFolders.js'>
</script>")
)
)
And my server.R
library(shiny)
library(ggplot2)
library(shinythemes)
library(shinyWidgets)
library(flowCore)
source("myanalysis.R")
options(shiny.maxRequestSize=50*1024^2)
shinyServer(function(input, output, session) {
observeEvent(input$go, {
df <- reactive({
print(input$fileIn)
# Below returns NULL, as it does not have any files in it yet.
print(input$fileout)
inFiles <- input$fileIn
if (is.null(inFiles))
return(NULL)
my.analysis(fs = tmp,output=input$fileout)
})
output$tbl <-renderPrint(
df()
)
output$results = renderPrint({input$mydata
})
})
})
Any help will be greatly appreciated.
Here are two options:
Option 1
It you only want to choose a folder in the sever side (that could be the local system if your app is running locally), you can use ShinyFiles.
Option 2
If your app is running in a server, then is not possible that you can write data to a local directory from your Shiny app. The solution in this case is to save the results in the server and later allow the user to download it using the downloadHandler function.

bsCollapsePanel within renderUI

I am using bsCollapse panels (from the shinyBS library) heavily in an app that I am working on. I'd like to be able to define a panel on the server-side as shown in the code. The code does not run and returns an error ERROR: argument is of length zero. The problem seems to be that bsCollapse won't accept a renderUI argument and requires bsCollapsePanel call to be in ui.R.
I've tried having bsCollapse() on the server-side, which works but is clunky as the individual panels then don't expand/collapse in the same way. I've also tried including outputOptions(output, "hipanel", suspendWhenHidden = FALSE), the idea being that my "hipanel" would be evaluated earlier, but this didn't work.
I think the key is that renderUI/uiOutput isn't returning the an object that's accepted by bsCollapsePanel (at least not at the right time), but I'm not sure what to do about it.
server.R
shinyServer(function(input, output){
output$hipanel<-renderUI({
bsCollapsePanel("hello",helpText("It's working!"))
})
})
ui.R
shinyUI(fluidPage(
mainPanel(
bsCollapse(
bsCollapsePanel("This panel works",helpText("OK")),
uiOutput("hipanel")
))))
It seems that bsCollapse needs a bsCollapsePanel so just add this in and then you can rnder whatever you want into the content:
library(shiny)
library(shinyBS)
ui <- shinyUI(fluidPage(
mainPanel(
bsCollapse(
bsCollapsePanel("This panel works",helpText("OK")),
bsCollapsePanel("hello",uiOutput("hipanel"))
)
)))
server <- shinyServer(function(input, output,session){
output$hipanel<- renderUI({
helpText("It's working!")
})
})
shinyApp(ui,server)
You can always dynamically create the whole thing
library(shiny)
library(shinyBS)
ui <- shinyUI(fluidPage(
mainPanel(
uiOutput("hipanel")
)))
server <- shinyServer(function(input, output,session){
output$hipanel<- renderUI({
bsCollapse(
bsCollapsePanel("This panel works",helpText("OK")),
bsCollapsePanel("hello",helpText("It's working!"))
)
})
})
shinyApp(ui,server)

How to programmatically collapse a box in shiny dashboard

I'm trying to collapse a box programmatically when an input changes. It seems that I only need to add the class "collapsed-box" to the box, I tried to use the shinyjs function addClass, but I don't know how to do that becuase a box doesn't have an id. Here as simple basic code that can be used to test possible solutions:
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
box(collapsible = TRUE,p("Test")),
actionButton("bt1", "Collapse")
)
)
server <- function(input, output) {
observeEvent(input$bt1, {
# collapse the box
})
}
shinyApp(ui, server)
I've never tried using boxes before so keep in mind that my answer might be very narrow minded. But I took a quick look and it looks like simply setting the "collapsed-box" class on the box does not actually make the box collapse. So instead my next thought was to actually click the collapse button programatically.
As you said, there isn't an identifier associated with the box, so my solution was to add an id argument to box. I initially expected that to be the id of the box, but instead it looks like that id is given to an element inside the box. No problem - it just means that in order to select the collapse button, we need to take the id, look up the DOM tree to find the box element, and then look back down the DOM tree to find the button.
I hope everything I said makes sense. Even if it doesn't, this code should still work and will hopefully make things a little more clear :)
library(shiny)
library(shinydashboard)
library(shinyjs)
jscode <- "
shinyjs.collapse = function(boxid) {
$('#' + boxid).closest('.box').find('[data-widget=collapse]').click();
}
"
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
useShinyjs(),
extendShinyjs(text = jscode, functions = "collapse"),
actionButton("bt1", "Collapse box1"),
actionButton("bt2", "Collapse box2"),
br(), br(),
box(id = "box1", collapsible = TRUE, p("Box 1")),
box(id = "box2", collapsible = TRUE, p("Box 2"))
)
)
server <- function(input, output) {
observeEvent(input$bt1, {
js$collapse("box1")
})
observeEvent(input$bt2, {
js$collapse("box2")
})
}
shinyApp(ui, server)