Problem using if and Else to render text in R shiny - if-statement

I am trying to set up a shiny app which allows individuals to select an option and then with that option a specific text appears if they select the other option different text appears.
Currently i am getting an error, i have tried to use the if else, I am new to shiny and fairly new to R so am struggling with the code.
I have tried playing about with using a reactive x but couldn't get it to work either potentially because this is not numeric?
# Sidebar with a select input for number of bins
sidebarLayout(
sidebarPanel(
selectInput(inputId = "Options",
label = "Option",
choices = c("Option 1","Option 2"))
),
# Show a text output
mainPanel(
textOutput(outputId = "ParticpantInformation1"),
textOutput(outputId = "ParticpantInformation2")
)),
# Define server logic required to rendertext
server <- function(input, output) {
if (input$Options=="Option 1") output$ParticpantInformation1 <- renderText("Option 1")
else output$ParticpantInformation2 <-renderText("Option 2")
I am hoping for it to render either one set of text or the other onto the main panel of the app
Currently i get an Error - "cannot coerce type 'closure' to vector of type 'character' "

You don't need that if(). You can directly refer to the user selection like this:
library(shiny)
ui <- fluidPage(
# Sidebar with a select input for number of bins
sidebarLayout(
sidebarPanel(
selectInput(inputId = "Options",
label = "Option",
choices = list("Option 1" = "My option 1 text", "Option 2" = "My option 2 text"))
),
# Show a text output
mainPanel(
textOutput(outputId = "ParticpantInformation")
))
)
server <- function(input, output, session) {
output$ParticpantInformation <- renderText({input$Options})
}
shinyApp(ui = ui, server = server)
For an alternative please see ?conditionalPanel, but for this case it's unnecessary complex.

Related

Scaling plotOutput height to fill the row in a sidebarLayout

I have a Shiny app with produces the following output. I would like the height of the graph to scale to fill the row which contains the sidebar, (down to some minimum dimension). This sidebar height changes depending on the data being examined.
The ui code I'm currently using is:
sidebarLayout(
sidebarPanel(
uiOutput("ridgeDates")
),
mainPanel(
plotOutput("ridgesPlot")
)
)
with the plot being rendered by renderPlot(...) This seems to adjust the /width/ automatically as I change the browser window width.
I've spent a while searching but can't find anything that does this. Is this possible?
We can use jQuery to track the height of the sidebar and set the height of the plot in css before creating the plotOutput. To do that, we need to use uiOutput in the UI, then render the plot dynamically.
So in the UI, the mainPanel will now have:
uiOutput("ridgePlot")
Then the plot is rendered in the server like so:
output$ridgePlot <- renderUI({
# plot data
output$ridges <- renderPlot({
# plot()
})
plotOutput("ridges")
})
Now we use shinyjs() to write a simple javascript function that sets the height value of the plot to the height of the sidebar. The sidebar is of class well, so we first get the height of the well, save it to a variable then set the ridges plot to the height of the variable, in javascript like this:
var newHeight = $('.well').outerHeight(); $('#ridges').height(newHeight)
I have used .outerHeight() because the well has extra padding that effectively gives it extra height than the height specified in the css rules for the well.
We can use this function in shiny using runjs() from shinyjs package. Since we need to get the height from the well after it has been rendered, we use observe and use it before the plotOutput inside the renderPlot, which is also inside the renderUI.
observe({
session$onFlushed(function() {
shinyjs::runjs("var newHeight = $('.well').outerHeight(); $('#ridges').height(newHeight)")
}, once=TRUE)
})
Putting it together in one Shiny app:
library(shiny)
library(shinyjs)
library(ggplot2)
ui = fluidPage(
useShinyjs(),
titlePanel("This is just a test!"),
sidebarLayout(
sidebarPanel(
uiOutput("ridgeDates")
),
mainPanel(
uiOutput("ridgePlot")
))
)
server = function(input, output, session) {
output$ridgeDates <- renderUI({
rng <- round(runif(1, 15, 21))
radioButtons("choose", "A changing list", choices = 1:rng)
})
output$ridgePlot <- renderUI({
datax <- matrix(c(1,2,3,4,5,6),6,1)
datay <- matrix(c(1,7,6,4,5,3),6,1)
titleplot<-"title"
summary <- "testing text"
output$ridges <- renderPlot({
# pl <- plot(datax, datay, main = titleplot, xlab = "input$axis1", ylab = "input$axis2", pch=18, col="blue")
ggplot(NULL, aes(datax, datay))+
geom_point(colour = "#1e90ff")
})
observe({
session$onFlushed(function() {
shinyjs::runjs("var newHeight = $('.well').outerHeight(); $('#ridges').height(newHeight)")
}, once=TRUE)
})
plotOutput("ridges")
})
}
# Run the application
shinyApp(ui = ui, server = server)
My example:

Hide widgets created in a tagList in shiny

I am recently building a shiny app, somewhere in my app I am expecting an arbitrary number of inputs which the user can specify from a line of selectInput() widgets.
Since the number of selectInput() widgets may be large, I would like it to happen that the next selectInput() widget only shows when the pervious one is filled by the user.
My idea is that I will:
create all possible selectInput() widgets in a tagList,
hide them all by default, and
show the next one when the previous one is filled.
I am fine with the first and third step, but when I tried to hide them all using the shinyjs function hide, it seems it does not work for input objects created in a tagList, it only works for those widgets that is created with a specific name, please see the example below:
library(shiny)
library(shinyjs)
ui <- fluidPage(
# Application title
titlePanel("Hello Shiny!"),
sidebarLayout(
# Sidebar with a slider input
sidebarPanel(
sliderInput("obs",
"Number of observations:",
min = 0,
max = 1000,
value = 500)
),
# Show a plot of the generated distribution
mainPanel(
useShinyjs(),
uiOutput('comparisons')
)
)
server <- shinyServer(function(input, output, session) {
observe(1, shinyjs::hide('compare_1') )
output$comparisons=renderUI({
out=tagList()
out=lapply(1:6, function(x){
selectizeInput(paste0('compare_',x),
label = 'Condition 1',
c('aa','bb', 'cc'))
})
out
})
})
shinyApp(ui, server)
Say I'm creating 6 selectInput widgets, name them compare_1 to compare_6, I also created a sliderInput called obs just to show as an example. In Server if I just say shinyjs::hide('obs'), the sliderInput will be hidden, but when I call shinyjs::hide('compare_1'), the selectInput is still there. Any idea will be appreciated!
Hi you can do that with conditinalPanel quite easy
ui <- fluidPage(
# Application title
titlePanel("Hello Shiny!"),
sidebarLayout(
# Sidebar with a slider input
sidebarPanel(
sliderInput("obs",
"Number of observations:",
min = 0,
max = 1000,
value = 500)
),
# Show a plot of the generated distribution
mainPanel(
useShinyjs(),
uiOutput('comparisons')
)
)
)
server <- shinyServer(function(input, output, session) {
output$comparisons=renderUI({
out=tagList(
selectizeInput(paste0('compare_1'),
label = 'Condition 1',
c("",'aa','bb', 'cc')),
lapply(2:6, function(x){
conditionalPanel(
paste0("input.compare_",x-1," != ''"),
selectizeInput(paste0('compare_',x),
label = paste0('Condition ',x),
c("",'aa','bb', 'cc'))
)
})
)
out
})
})
shinyApp(ui, server)

FileInput Button with selectInput in shiny..!

I am trying to take the speed variable from the "car" data set which I am uploading to the application. Basically Under select speed: I would like to have all the numbers appearing in the dataset$speed. Under selecInput, the choices should depend upond the data set I am uploading using fileInput. How can I complete this task. For now I have added the choices as 1,2,3. In theory there should be all values of the speed variable of cars data set.
library(shiny)
library(datasets)
##the file I am uploading
data(cars)
dataset=write.csv(cars, "dataset.csv")
ui=fluidPage(
actionButton("upload", "Upload File"),
bsModal("uploadFile", " ", "upload",
sidebarLayout(
sidebarPanel(
fileInput("file","Choose file to upload")
),
mainPanel(
tableOutput("contents")
)
)
),
sidebarLayout(
sidebarPanel(
column(3, selectInput("selectElement", "Select speed:", c(1,2,3),multiple =
T, selectize = F)
)
),
mainPanel(
)
)
)
server=function(input,output,session){
output$contents <- renderTable({
inFile <- input$file
if (is.null(inFile))
return(NULL)
read.csv(inFile$datapath)
})
}
shinyApp(ui,server)
My apologies in advance for a somewhat incomplete response: see below.
First of all, an answer to your query:
If you have a dataset like cars, to identify the "speed" labels you can do:
labls <- unique(cars$speed)
...
selectInput("selectElement", "Select speed:", labls, multiple =
T, selectize = F)
I was hoping to post a complete example, but the current logic (maybe because of the limited code posted?) does not seems right: how can the app a) leave to the user to select which file to use; and at the same time b) already filter for speed?
Of course it is possible that you plan to display datasets that have all a column called "speed", then it would make sense :)
Additionally, but this was not part of your question, you appear to use modal dialogues through the package shinyBS.
Since version 0.14 of shiny (around October 2016) shiny has a very good modal function and personally I think it would be better to use the native function instead.
I thougth to post a simple example derived from your code (but with the selectInput for speed commented out because, as mentioned, it does not appear right in the context of the example posted).
library(shiny)
library(datasets)
data(cars)
dataset = write.csv(cars, "dataset.csv")
labls <- unique(cars$speed) # I left this in the code
ui=fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("upload", "Upload File")
),
mainPanel(tableOutput("contents") )
))
server=function(input,output,session){
# Show modal when button is clicked.
observeEvent(input$upload, {
showModal(dataModal())
})
dataModal <- function(failed = FALSE) {
modalDialog(
fileInput('inputId', label=NULL, multiple = FALSE, accept = NULL, width = NULL, buttonLabel = "Browse...", placeholder = "No file selected")
# , selectInput("selectElement", "Select speed:", labls, multiple =
# T, selectize = F)
)
}
output$contents <- renderTable({
if (length(input$inputId )== 0) return(NULL)
inFile <- input$inputId
# if (is.null(input$selectElement )) return(NULL)
input$inputId
})
}
shinyApp(ui,server)

Shiny, create score from selectInputs

I'm very new to shiny and having some trouble creating a simple app. I am trying to use selectInputs to create a score. For example: if question 1=true and question 2=true then output value=2; if question 1=false and question 2=true then output value =1; and so on. I think the problem may be that I'm not grasping how reactivity works despite several reading the documentation (a lot). I also tried it with radio buttons and actions buttons with no luck.
Here's what I've got on the ui side:
ui.R
shinyUI(fluidPage(
titlePanel("title"),
sidebarLayout(
sidebarPanel(
selectInput("var1",
label = "Some question 1",
choices = c("True", "False"),
selected = "True"),
selectInput("var2",
label = "Some question 2",
choices = c("True", "False"),
selected = "True"),
submitButton(text = "Submit", icon = NULL, width = NULL)
)
)
)
)
The use of submitButton is generally discouraged in favor of the more versatile actionButton (which increases by 1 each time it is pressed).
In your server.R code you can create a reactive (calc_score) which takes a dependency on the input$submit (i.e. the actionButton) and then calculates the score (here checkboxes are used since TRUE and FALSE equals 1 and 0, respectively, so the sum of your checkbox values gives the score). Using isolate avoids a dependency on input$var1 and input$var2, so calc_score does not trigger when the checkboxes change (only when input$submit changes, i.e. the actionButton is pressed).
Finally, calc_score only triggers if it is actually consumed by an output (in this case in the output$score function which renders text that is then included in the UI via verbatimTextOutput("score"))
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("title"),
sidebarLayout(
sidebarPanel(
checkboxInput("var1", label = "Some question 1", value = TRUE),
checkboxInput("var2", label = "Some question 2", value = TRUE),
actionButton(inputId = "submit", label = "Submit", icon = NULL, width = NULL)
),
mainPanel(
verbatimTextOutput("score")
))))
server <- function(input, output) {
calc_score <- reactive({
input$submit
isolate(sum(c(input$var1, input$var2)))
})
output$score <- renderText({
calc_score()
})
}
shinyApp(ui = ui, server = server)

In Rshiny, How to replace old tabs with new one by selectInpout

Here is an existing example
library(shiny)
runExample("06_tabsets")
And you will see you can choose distribution type in radiobutton and there are three tabs "Plot", "Summary", and "Table".
My question is how can I add a selectInput under the sliderInput(number of observations) with two values. The default one is "NULL", the second one is "1". Once users select "1", the previous three tabs would disappear. Instead, a new tab would show whatever it content is.
This is the modified "06_tabsets". A select input is added and the UI is generated depending of the selection. The only difference is that is not using NULL, but two options. I could make it run with NULL. Let me know if this helps.
ui.R
library(shiny)
# Define UI for random distribution application
shinyUI(fluidPage(
# Application title
titlePanel("Tabsets"),
# Sidebar with controls to select the random distribution type
# and number of observations to generate. Note the use of the
# br() element to introduce extra vertical spacing
sidebarLayout(
sidebarPanel(
radioButtons("dist", "Distribution type:",
c("Normal" = "norm",
"Uniform" = "unif",
"Log-normal" = "lnorm",
"Exponential" = "exp")),
br(),
sliderInput("n",
"Number of observations:",
value = 500,
min = 1,
max = 1000),
selectInput("contentSelect", "Select content to dislay:", choices = c("1", "2"), selected = 1)
),
# Show a tabset that includes a plot, summary, and table view
# of the generated distribution
mainPanel(
uiOutput("content")
)
)
))
server.R
library(shiny)
# Define server logic for random distribution application
shinyServer(function(input, output) {
# Reactive expression to generate the requested distribution.
# This is called whenever the inputs change. The output
# functions defined below then all use the value computed from
# this expression
data <- reactive({
dist <- switch(input$dist,
norm = rnorm,
unif = runif,
lnorm = rlnorm,
exp = rexp,
rnorm)
dist(input$n)
})
# Generate a plot of the data. Also uses the inputs to build
# the plot label. Note that the dependencies on both the inputs
# and the data reactive expression are both tracked, and
# all expressions are called in the sequence implied by the
# dependency graph
output$plot <- renderPlot({
dist <- input$dist
n <- input$n
hist(data(),
main=paste('r', dist, '(', n, ')', sep=''))
})
# Generate a summary of the data
output$summary <- renderPrint({
summary(data())
})
# Generate an HTML table view of the data
output$table <- renderTable({
data.frame(x=data())
})
output$textA <- renderText({
paste(input$contentSelect, " A")
})
observeEvent(input$contentSelect, {
if (input$contentSelect == "1") {
output$content <- renderUI({
tabsetPanel(type = "tabs",
tabPanel("Plot", plotOutput("plot")),
tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Table", tableOutput("table"))
)
})
} else {
output$content <- renderUI({
tabsetPanel(type = "tabs",
tabPanel("A", textOutput("textA"))
)
})
}
})
})