Check Shiny inputs and generate warning on sidebar layout - r

I'm trying to create a shiny app that checks if an email provided in the sidebar is valid (in my case I authenticate directly to an API but in the code below I just create a toy example). I know that I can generate warnings and errors for inputs using validate and need (already read the shiny site on the topic here) but on most examples the errors and warnings are shown in the mainPanel() when generating a plot or something a like.
In my case, the main layout is only static text. What I'm trying to achieve is simple: the user inputs an email I check it, if it doesn't comply I generate some warning/error but it is shown somewhere else other than the mainPanel() because in my case there's no dynamic mainPanel.
Below is an example of what I'm trying to achieve.
library(shiny)
ui <- fluidPage(
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
textInput("email", "Email")
),
mainPanel()
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$email <-
renderUI({
validate(need(input$email == "",
"Introduce your email"))
validate(need(grep("gmail", input$email, value = TRUE)),
"Your email is not valid")
})
}
# Run the application
shinyApp(ui = ui, server = server)
Any idea how to achieve this? The error could be shown any where but on the mainPanel.

I am not 100% sure if I understand your question correctly, does the below do what you want? It displays a text message in the sidebar if one of your specified conditions is not met.
Hope this helps!
library(shiny)
ui <- fluidPage(
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
textInput("email", "Email"),
uiOutput('email_text')
),
mainPanel()
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$email_text <-
renderUI({
if(input$email == ""){
return(p("Please add your gmail e-mail address."))
}
if(!grepl("gmail", input$email)){
return(p("Your email is not a gmail e-mail address!"))
}
})
}
# Run the application
shinyApp(ui = ui, server = server)

Related

Constructing URL search parameters in Shiny app?

I have a Shiny app that wrangles a large csv file. Currently the user can select a facility_id number from a drop down menu to get a specific plot, see https://r.timetochange.today/shiny/Annual_Emissions2/. I would like to pass this id with a URL parameter like /?selected_facilities=1010040 so I can embed the plots in another website.
I have taken the code from How do you pass parameters to a shiny app via URL and tried to use it to update my selectInput() value in the server section of the Shiny app, but I don't really understand how the UI part is constructed so I am not getting it right. Any help would really be appreciated! Here is the relevant code:
#### shiny UI ####
facilities <- unique(ghg_emissions$facility_id)
ui <- fluidPage(
titlePanel("Annual Greenhouse Gas Emissions"),
sidebarLayout(
sidebarPanel(
selectInput("selected_facility",
"Select facility",
choices = facilities) # select input gives the drop down menu to select facilities
),
mainPanel(
plotlyOutput("facility_plot")
)
)
)
#### shiny server ####
server <- function(input, output, session) {
# Here you read the URL parameter from session$clientData$url_search
observe({
query <- parseQueryString(session$clientData$url_search)
if (!is.null(query[['selected_facility']])) {
updateSelectInput(session, "selected_facility", value = query[['selected_facility']])
}
})
Your UI is good, the issue with the updateSelectInput, use selected rather than value and include choices.
Minimal working example:
library(shiny)
facilities <- seq(1:5)
ui <- fluidPage(
selectInput("selected_facility", "Select facility", choices = facilities)
)
server <- function(input, output, session) {
observe({
#Get URL query
query <- parseQueryString(session$clientData$url_search)
#Ignore if the URL query is null
if (!is.null(query[['selected_facility']])) {
#Update the select input
updateSelectInput(session, "selected_facility", selected = query[['selected_facility']], choices = facilities)
}
})
}
shinyApp(ui, server)
To test, run your shiny app, click 'Open in Browser' and append your query to the URL, e.g.
127.0.0.1:6054/?selected_facility=4

using input variables in reactive part Rshiny

I quiet novice to Rshiny. I want to capture the information(variables) entered by the user and pass them to python script, which I would be calling in the R itself. But initially I need help in the server code, where I am not doing something correct in the reactive code part.
My code till now is:
library(shiny)
ui <- fluidPage(
headerPanel(
titlePanel("RADP CR Prediction Tool"),
br(),
tags$head(tags$script(src = "message-handler.js")),
textInput('Region', label = 'Enter the region'),
textInput('Regulatory', label = 'Enter the regulatory status'),
textInput('Description', label = 'Enter the description for the CR'),
br(),
br(),
actionButton("goButton", "Go!"),
mainPanel(
# Output: Formatted text for caption ----
h3(textOutput("caption", container = span)),
# Output: Verbatim text for data summary ----
verbatimTextOutput("summary"),
# Output: HTML table with requested number of observations ----
tableOutput("view")
)
)
server <- function(input, output, session) {
region_input=reactive(input$Region)
regulatory_input <- reactive(input$Regulatory)
description_input <-reactive(input$Description)
observeEvent(input$do, {
session$sendCustomMessage(type = 'testmessage',
message = 'Thank you for clicking')
})
}
shinyApp(ui, server)
When I run the code it gives me Error: unexpected symbol in:
")
server"
I need to use the regulatory_input, description_input and region_input as R variables, so that I can do further analysis.
You're missing a parentheses. You close the mainPanel and the headerPanel but you don't have a close parentheses for the fluidPage function.
You can see this in RStudio by putting the cursor after the ) on line 25, you will see that the open ( in headerPanel( is highlighted. You can also select you code and then hit ctrl I to indent it. You'll see that the server function is "inside" the fluidPage function.
This may seem like a small thing, but paying attention to details like this is critical for programming. In my experience, 9 times out of 10, when something isn't working, its some small thing like this I forgot.
As for the question in your title, the values of your inputs are already in a variable: input$ID_OF_INPUT. Just use that as you would any other variable. There is no reason to copy the value out of it with something like: variable <- reactive({input$id}). Just use input$id wherever you would use variable.

How to present an output without waiting for the rest of the script to run in R Shiny

I have a Shiny app that should calculate a value, present it and then use the same value for further more expensive computation. The problem is that it shows me the output only after it finishes evaluating the whole script. Here is a simple example:
library(shiny)
ui <- fluidPage(
titlePanel("test"),
sidebarLayout(
sidebarPanel(
textInput("text_in","Enter text here",value = "This is text to process"),
actionButton("go", "Go")
),
mainPanel(
textOutput("first_text"),
textOutput("results")
)
)
)
# Define server logic
server <- function(input, output) {
num_letter<-eventReactive(input$go, {
nchar(input$text_in)})
output$first_text <- renderText(num_letter())
sec_calculation<-eventReactive(num_letter(), {
Sys.sleep(3)
num_letter()*num_letter()})
output$first_text <- renderText(num_letter())
output$results <- renderText(sec_calculation())
}
# Run the application
shinyApp(ui = ui, server = server)
I added the Sys.sleep so it will be easier to see the problem. I would like to get the first output without waiting for the second one.
This is not currently possible (at least not with native shiny code - you can always hack a workaround). An open issue for this exists on the shiny github repository: https://github.com/rstudio/shiny/issues/1705

Multi line text inputs in shiny

What are my options to realize text inputs with multiple lines/line breaks (either explicit or just soft-wraps for nicer output in the UI) in shiny?
I'd like to implement an app that has a description/details field and the content being entered will most likely be more than just one line.
Basically, I'm looking for something to realize a similar functionality of the very text input box of stackoverflow I'm writing this question in: line breaks, scroll bar and/or (auto-)adjustment of height.
Example
# UI ---------------------------------------------------------------------
ui <- fluidPage(
p(),
textInput("title", "Title"),
textInput("description", "Description"),
tags$hr(),
h3("Database state"),
DT::dataTableOutput("datatable")
)
# Server ------------------------------------------------------------------
server <- function(input, output, session) {
output$datatable <- DT::renderDataTable(
data.frame(
Title = input$title,
Description = input$description,
stringsAsFactors = FALSE
)
)
}
shinyApp(ui, server)
Try using textAreaInput instead of textInput.
With the former you can set height and width, and it automatically will wrap to next line if line is too long.
Here is where it is mentioned in the docs.

Stop functions starting in shiny until button pressed

I have begun to create a web app using shiny where a user enters a search term and tweets containing that term are returned.
When I load this app the searchTwitter function begins automatically and on the main panel there is the error: Error: You must enter a query.
The search term is entered in the textInput box and there is a submitButton. You can enter a term and it works fine but I don't want the error to be the first thing the user sees.
ui.R:
library(shiny)
shinyUI(pageWithSidebar(
headerPanel("Twitter Generator"),
sidebarPanel(
textInput("search", "Search Twitter For:", value = ""),
submitButton("Search")
),
mainPanel(
h3(textOutput("search")),
tableOutput("view"),
)
))
server.R:
library(shiny)
library(twitteR)
shinyServer(function(input, output) {
datasetInput <- reactive(function(){
rawTweets <- twListToDF(searchTwitter(paste(input$search)))
rawTweets$cleanText <- as.vector(sapply(rawTweets$text, CleanTweet))
rawTweets[, colnames(rawTweets) != "created"]
})
output$search <- reactiveText(function() {
input$search
})
output$view <- reactiveTable(function() {
head(datasetInput())
})
})
Thanks for your help
This is a logical request for and from your application design, and you should think through how to do it.
One easy way would be to add a tickbutton providing a true/false and to skip the actual twitter search if the value is FALSE. You may need to cache the previous value of rawTweets, or set it to NULL, or ...
mainPanel(
h3(textOutput("search")),
tableOutput("view")
)
try it without the second ","

Resources