Shiny.setInputValue is not a function error - r

I am baffled why the following code produces the "Shiny.setInputValue is not a function" error:
library(shiny)
library(htmltools)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Test"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
),
# Show a plot of the generated distribution
mainPanel(
shiny::tags$script(htmltools::HTML('
quantityaa = 1;
console.log(quantityaa);
Shiny.setInputValue("hi", quantityaa);
'))
,
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
hi <- reactive({ input$hi})
print(hi)
}
# Run the application
shinyApp(ui = ui, server = server)
What is wrong with this code that produces this error? I cannot see anything wrong with it, but I must be missing something.

That's because Shiny is not ready yet. Use the shiny:connected event:
$(document).on("shiny:connected", function() {
// your awesome JavaScript here can use Shiny.setInputValue
});

Related

In R Shiny, how do you paste a user's selected input from UI into a reactive object in server?

super new to shiny, have a problem that seems like it should be basic reactive programming but I haven't been able to find a solution that's worked so far.
Essentially, I want to take the user's selected input from the UI and paste it into a simple object in the server that will react/update when a new input is chosen.
The object will be concatenated into a full API call, and I wish to rerun the API call in the server with the reactive object updated each time a new input is chosen for it (note: the API cannot be run without an access code which is part of a corporate account, so apologies for my hesitance to put my full code but I just need help with this one functionality.)
In code below:
with Dollar General as the default selection in the selectInput, I would like the object, query, to be the character string "dollar%20general", and reactively change to "walmart" should Walmart be selected
Thanks!
ui <- fluidPage
sidebarLayout(
sidebarPanel(
selectInput("company", "Choose company:",
c("Dollar General" = "dollar%20general",
"Dollar Tree" = "dollar%20tree",
"Walmart" = "walmart"))
...
server <- function(input,output) {
...
query <- paste(input$company)
...
you can use reactiveValues() and observe. This should work:
library(shiny)
# Define UI for application
ui <- fluidPage(
# your input
sidebarLayout(
sidebarPanel(
selectInput("company", "Choose company:",
c("Dollar General" = "dollar%20general",
"Dollar Tree" = "dollar%20tree",
"Walmart" = "walmart"))
),
# Determine Output
mainPanel(
textOutput("showInput") # you need to render this in your server file
)
)
)
server <- function(input, output) {
# Show what was selected
query <- reactiveValues()
observe(
query$test <- paste(input$company, "and test", sep = " ")
)
output$showInput <- renderText({ #based on what you defined in the ui
query$test
})
}
# Run the application
shinyApp(ui = ui, server = server)
Create two files named ui.R and server.R store the UI logic in ui.R and backend/object logic in server.R. Below is the implementation.
UI file
# UI of app
ui <- fluidPage(
# input
sidebarLayout(
sidebarPanel(
selectInput("company", "Choose company:",
c("Dollar General" = "dollar%20general",
"Dollar Tree" = "dollar%20tree",
"Walmart" = "walmart"))
),
# Output
mainPanel(
textOutput("Input")
)
)
)
Server/Backend File
server <- function(input, output) {
# Show what was selected
output$Input <- renderText({ #based on what you defined in the ui
input$company
})
}
Now store these in a directory and then call runApp function.
~/newdir
|-- ui.R
|-- server.R
runApp("newdir")

Modules in separated server.R and ui.R files

Is it possible to create modules in a Shiny App which is written down in separated app.R, server.R and ui.R files?
All the examples I found are one app.R file with embedded server and ui functions in. See example 1, example 2!, example 3!
(I took the code from this last example for this test).
I tried to run this app:
app.R
library(shiny)
# load module functions
source("hello_world.R")
# Run the application
shinyApp(ui = ui, server = server)
ui.R
#ui.R
library(shiny)
#source("hello_world.R")
ui <- fluidPage(
titlePanel("Using of Shiny modules"),
fluidRow(
# Call interface function of module "hello_world"
hello_worldUI(id = "id_1")
)
)
server.R
#server.R
library(shiny)
source("hello_world.R")
server <- function(input, output, session) {
# Call logic server function of module "hello_world"
callModule(module = hello_world, id = "id_1")
}
# UPDATE! -> my Error comes from this line of code in server.R file:
#shinyApp(ui = ui, server = server)
#Removing the line above solve the problem.
hello_world.R
#module 1: hello_world
# Function for module UI
hello_worldUI <- function(id) {
ns <- NS(id)
fluidPage(
fluidRow(
column(2, textInput(ns("TI_username"), label = NULL, placeholder = "your name")),
column(2, actionButton(ns("AB_hello"), label = "Hello !"))
),
hr(),
fluidRow(
column(12, textOutput(ns("TO_Hello_user")))
)
)
}
# Function for module server logic
hello_world <- function(input, output, session) {
# When user clicks on "Hello" button : Update reactive variable "name"
name <- eventReactive(input$AB_hello, {
return(input$TI_username)
})
# Show greetings
output$TO_Hello_user <- renderText({
if (name() %in% "") {
return("Hello world !")
} else {
return(paste("Hello", name(), "!"))
}
})
}
But I got this error:
Warning: Error in force: object 'ui' not found
52: force
51: uiHttpHandler
50: shinyApp
Error in force(ui) : object 'ui' not found
The ui and server objects are not known to the app unless you define them in the same file and they are generated at run time, or you explicitly call them from outside files before shinyApp(). Change your app.R like below, and it should work:
library(shiny)
# load module functions
source("hw.R")
# load ui elements
source("ui.R")
# load server function
source("serv.R")
# Run the application
shinyApp(ui = ui, server = server)

Image output in shiny app

I am trying to include an image in a shiny app. I want: "if it is type 1 plot "this image", if it is type 0 plot "this other image". I know that I have to put the jpg files into the folder where the app.R is and then call it but I do not know how.
This is the code I have used until now (it works), I just have to include the images in the render.
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Myapp"),
#Inputs
dateInput(inputId = "dob", label="Birth"),
dateInput(inputId = "ad", label="Date"),
actionButton("Submit", icon("fas fa-magic"), label="Submit"),
#Outputs
textOutput(outputId = "textR"),
imageOutput(outputId = "imageR1"),
imageOutput(outputId="imageR2")
)
# Define server logic required to draw a histogram
server <- function(input, output) {
#my output should be named textR and imageR1, imageR2
observeEvent(input$Submit,
output$textR<-renderText({
v1<-as.numeric(as.Date(input$ad,format="%Y/%m/%d") - as.Date(input$dob, format="%Y/%m/%d"))/30.5
value_v1<-ifelse(v1>48, "type1", "type2")
print(value_v1)
}))
}
# Run the application
shinyApp(ui = ui, server = server)
It is bad practice to define an output object inside an observeEvent. In this case, independent on the choice of how to switch the images, I would advice to use an eventReactive - let's call that myval. That creates a reactive which only changes when a certain event happens, in this case a click on the submit button. We can then refer to this in the body of the renderText statement, so that can simply become:
output$textR<-renderText({
print(myval())
})
Secondly, for the outputting of images, you should place those in the www directory, see here. We can then create an ui element with renderUI and UIOutput, in which we use the value of our eventReactive myval() to select the image to display.
A working example is given below. Note that I saved it as app.R, and used the folder structure of the referred link, so:
| shinyApp/
| app.R
| www/
| zorro.jpg
| notzorro.jpg
Hope this helps!
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Myapp"),
#Inputs
dateInput(inputId = "dob", label="Birth"),
dateInput(inputId = "ad", label="Date"),
actionButton("Submit", icon("fas fa-magic"), label="Submit"),
#Outputs
textOutput(outputId = "textR"),
uiOutput(outputId = "my_ui")
)
# Define server logic required to draw a histogram
server <- function(input, output) {
myval <- eventReactive(input$Submit,
{
v1<-as.numeric(as.Date(input$ad,format="%Y/%m/%d") - as.Date(input$dob, format="%Y/%m/%d"))/30.5
return(ifelse(v1>48, "type1", "type2"))
})
output$textR<-renderText({
print(myval())
})
output$my_ui<-renderUI({
if(myval()=='type1')
img(src='zorro.jpg', height = '300px')
else
img(src='notzorro.jpg', height = '300px')
})
}
# Run the application
shinyApp(ui = ui, server = server)

R Shiny - Sequential text output

I want to print a text first, before processing the code and then print a confirmation after the code is executed.
Here is my code (ui and server of app.R):
All unspecified variables are initiated within the app.R file.
ui <- fluidPage(
# Application title
titlePanel(h1("Order2Ship", align="center")),
# Sidebar iputs
sidebarLayout(
sidebarPanel( #LONG LIST OF INPUTS
),
# On Screen output
mainPanel(
textOutput("START"),
textOutput("Confirm")
)
)
)
# Underlining code for output (computes the whole each time an input is changed)
server <- function(input, output) {
observeEvent(input$Do, { # ignores all return values
output$START <- renderText({"Starting Analysis"})
O2S( #LONG LIST OF PARAMETERS, FROM INPUTS
)
output$Confirm <- renderText({"Analysis Done"})
})
}
# Run the application
shinyApp(ui = ui, server = server)
I do not need any returns from the function O2S, it basically takes one file as input and generates a solution file. But, both the text outputs are showing at the same time, after the function has run. I cannot figure it out. I just started out with Shiny, so sorry for such a naïve question.
Hi you can use shinyjs to create a chainevent something like this
library(shinyjs)
library(shiny)
ui <- fluidPage(
# Application title
titlePanel(h1("Order2Ship", align="center")),
# Sidebar iputs
sidebarLayout(
sidebarPanel( #LONG LIST OF INPUTS
actionButton(inputId = "Do",
label = "Start")
),
# On Screen output
mainPanel(
textOutput("START"),
textOutput("Confirm"),
useShinyjs()
)
)
)
# Underlining code for output (computes the whole each time an input is changed)
server <- function(input, output) {
startText <- eventReactive({input$Do},{
runjs("Shiny.onInputChange('analysisStarted',Date.now())")
"Starting Analysis"
},
ignoreInit = TRUE)
output$START <- renderText({startText()})
observeEvent(input$analysisStarted, { # ignores all return values
temp <- NULL
for(i in seq(50000)){
temp <- c(temp,i)
}
runjs("Shiny.onInputChange('analysisFinished',true)")
},
ignoreInit = FALSE)
confirmText <- eventReactive({input$analysisFinished},{
"Analysis Done"
},
ignoreInit = FALSE)
output$Confirm <- renderText({confirmText()})
}
# Run the application
shinyApp(ui = ui, server = server)
hope this helps!

conditionalPanel in R/shiny

Quick question on conditionalPanel for shiny/R.
Using a slightly modified code example from RStudio, consider the following simple shiny app:
n <- 200
# Define the UI
ui <- bootstrapPage(
numericInput('n', 'Number of obs', n),
conditionalPanel(condition = "input.n > 20",
plotOutput('plot') ),
HTML("Bottom")
)
# Define the server code
server <- function(input, output) {
output$plot <- renderPlot({
if (input$n > 50) hist(runif(input$n)) else return(NULL)
})
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
My objective is to hide the graph and move up the HTML text to avoid a gap. Now, you can see that if the entered value is below 20, the graph is hidden and the text "Bottom" is moved up accordingly. However, if the entered value is larger than 20, but smaller than 50, the chart function returns NULL, and while no chart is shown, the text "Bottom" is not moving up.
Question is: is there a way I can set a conditionalPanel such that it appears/is hidden based on whether or not a plot function returns NULL? The reason I'm asking is because the trigger a bit complex (among other things it depends on the selection of input files, and thus needs to change if a different file is loaded), and I'd like to avoid having to code it on the ui.R file.
Any suggestions welcome,
Philipp
Hi you can create a condition for conditionalPanel in the server like this :
n <- 200
library("shiny")
# Define the UI
ui <- bootstrapPage(
numericInput('n', 'Number of obs', n),
conditionalPanel(condition = "output.cond == true", # here use the condition defined in the server
plotOutput('plot') ),
HTML("Bottom")
)
# Define the server code
server <- function(input, output, session) {
output$plot <- renderPlot({
if (input$n > 50) hist(runif(input$n)) else return(NULL)
})
# create a condition you use in the ui
output$cond <- reactive({
input$n > 50
})
outputOptions(output, "cond", suspendWhenHidden = FALSE)
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
Don't forget to add the session in your server function and the outputOptions call somewhere in that function.

Resources