Shiny seems to only accept the final output of any provided to mainPanel in ui.R. An earlier SO question raised this but reached no satisfactory solution. The documentation for mainPanel suggests this should be possible:
Description: Create a main panel containing output elements
The following code illustrates:
server.R
library(shiny)
shinyServer(
function(input, output) {
plotInput <- reactive({
list(plot = plot(1:10),
txt = "My reactive title")
})
output$myplot <- renderPlot({ plotInput()$plot })
output$txt <- renderText({ plotInput()$txt })
}
)
ui.R
require(shiny)
pageWithSidebar(
headerPanel("Multiple outputs to mainPannel"),
sidebarPanel(),
mainPanel({
# only the last output works
h1(textOutput("txt"))
plotOutput("myplot")
p("see what I mean?")
})
)
Does anyone know if this is a bug, or how to work around it?
Try
mainPanel(
# only the last output works
h1(textOutput("txt")),
plotOutput("myplot"),
p("see what I mean?")
)
Related
Shiny beginner here: I want to load a different dataset depending on which action-button gets clicked on. Since the processing from there on will be the same for any dataset, I want to store them in the same reactive expression, here dataset().
See my code:
library(shiny)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("gohere", "dataset1"),
actionButton("gothere", "dataset2")
),
mainPanel(
tableOutput("dataset")
),
)
)
)
server <- function(input, output) {
dataset <- eventReactive(input$gohere, {
mtcars
})
dataset <- eventReactive(input$gothere, {
cars
})
output$dataset <- renderTable({
dataset()
})
}
shinyApp(ui = ui, server = server)
I expect this code to load mtcars into dataset when actionButton "gohere" is clicked and proceed with renderTable and to load cars into dataset when actionButton "gothere" is clicked and proceed likewise.
However: If I click actionButton "gothere" everything works as expected, if I click "gohere" nothing happens. If I change the order of "gohere" and "gothere" inside the server- function it's the other way around.
What does the second eventReactive() do with dataset that completly invalidates the first eventReactive() ?
EDIT: And if it is overwriting it, what is it overwriting it with?
This works like ordinary R programming: your two reactive conductors are R objects with the same name, so the second one overwrites the first one.
You can use a reactive value and some observers:
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("gohere", "dataset1"),
actionButton("gothere", "dataset2")
),
mainPanel(
tableOutput("dataset")
),
)
)
server <- function(input, output) {
dataset <- reactiveVal(mtcars)
observeEvent(input$gohere, {
dataset(mtcars)
})
observeEvent(input$gothere, {
dataset(cars)
})
output$dataset <- renderTable({
dataset()
})
}
shinyApp(ui = ui, server = server)
I have a shiny code like in the below. I need to define variables as reactiveValues to be updatable (or I could define them I think as global but then I have to press clean objects from Rstudio which is not very user-friendly).I try to run a validate code to check for existence of the data I have defined as reactiveValues. validate(need(exists("GSEmRNA$d"),message="Dataframe not found")) yields "Dataframe not found" thus, does not plot my boxplot. If I define them as global variables and forget to press clean objects, code might mix up as old data can be passed as if it is new. Any help is appreciated.
server.R
shinyServer(function(input, output) {
observeEvent(input$GoButton,{
dataset <- data.frame(first= c(1,5,9),second=c(8,5,13), third=c(10,3,17))
GSEmRNA <- reactiveValues(d=dataset)
})
output$BoxplotDataset <- renderPlot({
if (input$GoButton== 0) {return()}
else{
validate(need(exists("GSEmRNA$d"),message="Dataframe not found"))
boxplot(GSEmRNA$d)}
})
})
ui.R
library(shiny)
shinyUI(pageWithSidebar(
headerPanel("Dataset Selection"),
sidebarPanel(
actionButton("GoButton","GO")
),
mainPanel(
wellPanel(
column(8, plotOutput("BoxplotDataset")
)
)
)))
FOR THE RECORD, I ALSO POSTED THIS QUESTION TO SHINY GOOGLE DISCUSS GROUP https://groups.google.com/forum/#!topic/shiny-discuss/ZV5F6Yy-kFg
Here are the updated code. The points are:
library(shiny)
server <-shinyServer(function(input, output) {
GSEmRNA <- reactiveValues(d=NULL) #define it ouside
observeEvent(input$GoButton,{
dataset <- data.frame(first= c(1,5,9),second=c(8,5,13), third=c(10,3,17))
GSEmRNA$d <- dataset #assign it inside
})
output$BoxplotDataset <- renderPlot({
validate(need(GSEmRNA$d,"Dataframe not found")) # changed as well
boxplot(GSEmRNA$d)
})
})
ui <- pageWithSidebar(
headerPanel("Dataset Selection"),
sidebarPanel(
actionButton("GoButton","GO")
),
mainPanel(
wellPanel(
column(8, plotOutput("BoxplotDataset")
)
)
))
runApp(list(ui=ui,server=server))
Defined the reactiveValues outside of the observeEvent
Changed the reactiveValues inside of the observeEvent
Changed the validate and need.
I have a shiny app which calls an external function based on user input. This function updates a data frame based on the input so it can be used to render a plot.
getData function()
getData= function(inpName)
{
// a piece of code based on inpName
}
shinyUI.R
library(shiny)
shinyUI(fluidPage(
titlePanel("title"),
sidebarLayout(
sidebarPanel(
textInput("name","Enter a name")),
mainPanel())
))
shinyServer.R
library(shiny)
shinyServer(function(input,output)
{
getData=reactive({getData(input$name) })
})
No matter what I try I just can't seem to get the shinyServer to call the function and update a df. Could someone advise what am doing wrong? Appreciate any help.
You don't want to be overwriting getData in the server function.
library(shiny)
getData <- function(inpName)
if (inpName %in% names(mtcars)) mtcars[,inpName] else NULL
shinyApp(
shinyUI(fluidPage(
titlePanel("title"),
sidebarLayout(
sidebarPanel(
textInput("name","Enter a name")),
mainPanel(
verbatimTextOutput('tab')
))
)),
shinyServer(function(input, output, session) {
## The first way
## dat <- reactive({ getData(input$name) })
## The other way
vals <- reactiveValues(dat=NULL)
observeEvent(input$name, vals$dat <- getData(input$name))
output$tab <- renderPrint({ summary(vals$dat) })
})
)
I want to create a reactive data frame with a reactive column name in shiny. However this is throwing error. I have provided the code below.. The error is being caused by an () followed by =, but I cant find a way around. Any help will be appreciated
ui.R
library(shiny)
shinyUI(fluidPage(
titlePanel("Tool"),
sidebarLayout(
sidebarPanel(
textInput("Item","Enter Item Name"),
div(class='row-fluid',
div(class='span6', numericInput("sales1","Enter Sales",value=0),numericInput("sales2","Enter Sales",value=0)),
div(class='span6', numericInput("prices1","Enter price",value=0),numericInput("prices2","Enter price",value=0))
)),
mainPanel(
dataTableOutput("table")
)
)
))
server.R
library(shiny)
shinyServer(function(input, output) {
prices<-reactive({
c(input$prices1,input$prices2)
})
sales<-reactive({
c(input$sales1,input$sales2)
})
combined<-reactive({
data.frame(prices(),sales())
})
combined_final<-reactive({
mutate(combined(),Rev=prices()*sales())
})
namerev<-reactive({
as.character(paste("Rev",input$Item,sep="_"))
})
combined_final_rename<-reactive({
rename_(combined_final(),namerev() ="Rev")
})
output$table<-renderDataTable({
combined_final_rename()
})
})
If I understood the question correctly, you might need something like that:
combined_final_rename<-reactive({
d <- combined_final()
colnames(d)[colnames(d)=='Rev'] <- namerev()
d
})
I am trying to have multiple html outputs in my shiny App but it seems like it can only show one at a time.
My UI is:
# ui.R
shinyUI(
mainPanel(
tableOutput("view"),
plotOutput("view2")
))
And my server is:
# server.R
library(googleVis)
library(RMySQL)
shinyServer(function(input, output) {
datasetInput <- reactive({
"try2" = subset(try1, idCampaign == input$inputId)
})
output$view <- renderGvis({
gvisTable(datasetInput(),options=list(width=1000, height=270, col='blue'))
})
output$view2 <- renderGvis({
gvisScatterChart(datasetInput2())
})
})
in the output to view2 you use datasetInput2() , this should be datasetInput(). Here datasetInput() just represents a dynamic version of a dataframe, you can use it in as many functions as you want, there is no need to index it.
alternatively i think you can use the tabsetPanel to divide your main page into certain parts and assign output objects to each of your tabPanel.