Declaring variables inside Shiny application in R - r

I have a shiny application, where i take some input from the user, which should serve as arguments for some functions to be served on he backend.
in my UI on the home page, i have a textInput, which should be served as a global variable (because it should be used in almost all functions).
but as far as i have tried there is NO way to declare a function inside the server function.
Sample code:
UI component
textInput(inputId = "app_name", label="Please enter the name of your application", value="app_x")
))
#this is declared as a global variable in the top
application_name <- NULL
...
#inside server function
application_name <<- input$app_name
causes this error:
Error in .getReactiveEnvironment()$currentContext() :
Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)

I've dealt with this error several times. In most cases it's caused because Shiny has no way of knowing which value this is. For example:
in ui.R:
ui <- fluidPage(
textInput("text","Text")
actionButton("button","Submit")
)
in server.R:
observeEvent(input$button,{
result <- yourFunction(input$text$value)
})
If you need to use this value as a variable (Not as the argument of a function), you can also use what you where using, but it needs to be inside a reactive event (observeEvent, reactiveValue, etc.)
in server.R:
observeEvent(input$button,{
neededText <- input$text$value
.... Do what you need with the text....
})
In your specific case, you can pass the variable as an argument to the functions when a specific event occurs (Since I don't know what your app does)
EDIT:
You can also use reactive as so:
in server.R:
text_reactive <- reactive({
input$text
})

Related

Advantages of reactive vs. observe vs. observeEvent

I've reading everything I can about shiny reactive programming. I'm a bit confused. The following all work but what is the preferred method and why? Obviously the example below is simple but will I run into trouble when creating a larger application with any of the methods?
I've been tending to gravitate towards the style in server code #1. Reason being, is that I'm able to break up the if statements. To me this seems much more readable. Again, the simple examples below aren't terribly complex but you can easily imagine how server code 2 and server code 3 could get very confusing with lots of nested if / if else statements.
UI Code
library(shiny)
ui <- fluidPage(
selectInput(inputId = 'choice',
label = 'Choice',
choice = c('Hello','Goodbye'),
selected = c('Hello')
),
textOutput('result')
)
Server Code 1
server <- function(input,output,session)({
text <- reactiveValues()
observe({
if (input$choice == 'Hello') {
text$result <- 'Hi there'
}
})
observe({
if (input$choice == 'Goodbye') {
text$result <- 'See you later'
}
})
output$result <- renderText({
text$result
})
})
shinyApp(ui = ui, server = server)
Server Code 2
server <- function(input,output,session)({
getStatus <- reactive({
if (input$choice == 'Hello') {
'Hi there'
} else if (input$choice == 'Goodbye'){
'See you later'
}
})
output$result <- renderText({
getStatus()
})
})
shinyApp(ui = ui, server = server)
Server Code 3
server <- function(input,output,session)({
text <- reactiveValues()
observeEvent(input$choice,{
if (input$choice == 'Hello') {
text$result <- 'Hi there'
} else if (input$choice == 'Goodbye') {
text$result <- 'See you later'
}
})
output$result <- renderText({
text$result
})
})
shinyApp(ui = ui, server = server)
First off this stuff is sort of ambiguous, and not very intuitive in some ways, it even says so on the Shiny blog!
Here is my best understanding of the topic..
Lets start with reactive
The reactive function allows a user to monitor the status of an input or other changing variable and return the value to be used elsewhere in the code. The monitoring of a reactive variable is considered lazy, "Reactive expressions use lazy evaluation; that is, when their dependencies change, they don't re-execute right away but rather wait until they are called by someone else.(Source)". You show this well in example 2, as you can call the variable inside the renderText environment, once called the code inside the reactive call executes and re-evaluates the variable.
For science nerds, this is a lot like quantum mechanics in that by calling the reactive variable (observing it) causes it to change by re-evaluating, too much of a stretch?
Now to observe
Observe is similar reactive, the main difference is that it does not return any values to any other environment besides its own, and it is not lazy. The observe function continually monitors any changes in all reactive values within its environment and runs the code in it's environment when these values are changed. So, observe is not a "lazy" evaluation since it does not wait to be called before it re-evaluates. Again note that you cannot assign variables from observe.
For sake of experiment:
server <- function(input,output,session)({
observe({
if (input$choice == 'Hello') {
getStatus <- 'Hi there'
}
})
observe({
if (input$choice == 'Goodbye') {
getStatus <- 'See you later'
}
})
output$result <- renderText({
getStatus
})
})
shinyApp(ui = ui, server = server)
What is important to notice is that during the code executed in observe, we can manipulate outside environment reactive variables. In your case you assign text <- reactiveValues() and then manipulate that by calling text$result <- 'Hi there'. We can also do things like update selectInput choices, or other shiny widgets, but we cannot assign any non-reactive variables in this environment like our getStatus in the example above. And this idea is mentioned on the observe documentation,
"An observer is like a reactive expression in that it can read reactive values and call reactive expressions, and will automatically re-execute when those dependencies change. But unlike reactive expressions, it doesn't yield a result and can't be used as an input to other reactive expressions. Thus, observers are only useful for their side effects (for example, performing I/O)(Source)"
Lastly, observeEvent
The best way to use observeEvent is to think of it as a defined trigger, as in it watches one event or change in a variable, and then fires when the event happens. I most commonly use this to watch input to buttons, as that is a defined event in which I want things to happen after the button is pushed. It uses an isolate environment which I think is the perfect name for how this function works.
Inside this environment we can call a bunch of reactive variables, but we only define one as the trigger. The main difference between observeEvent and observe being the trigger, as observe runs anytime anything changes, and observeEvent waits for the trigger. Note that this environment is similar to observe in that it does not return non-reactive variables.
Summary
Here is an example that brings all these ideas together:
library(shiny)
ui<-
fluidPage(
fluidRow(
column(4,
h2("Reactive Test"),
textInput("Test_R","Test_R"),
textInput("Test_R2","Test_R2"),
textInput("Test_R3","Test_R3"),
tableOutput("React_Out")
),
column(4,
h2("Observe Test"),
textInput("Test","Test"),
textInput("Test2","Test2"),
textInput("Test3","Test3"),
tableOutput("Observe_Out")
),
column(4,
h2("Observe Event Test"),
textInput("Test_OE","Test_OE"),
textInput("Test_OE2","Test_OE2"),
textInput("Test_OE3","Test_OE3"),
tableOutput("Observe_Out_E"),
actionButton("Go","Test")
)
),
fluidRow(
column(8,
h4("Note that observe and reactive work very much the same on the surface,
it is when we get into the server where we see the differences, and how those
can be exploited for diffrent uses.")
))
)
server<-function(input,output,session){
# Create a reactive Evironment. Note that we can call the varaible outside same place
# where it was created by calling Reactive_Var(). When the varaible is called by
# renderTable is when it is evaluated. No real diffrence on the surface, all in the server.
Reactive_Var<-reactive({c(input$Test_R, input$Test_R2, input$Test_R3)})
output$React_Out<-renderTable({
Reactive_Var()
})
# Create an observe Evironment. Note that we cannot access the created "df" outside
# of the env. A, B,and C will update with any input into any of the three Text Feilds.
observe({
A<-input$Test
B<-input$Test2
C<-input$Test3
df<-c(A,B,C)
output$Observe_Out<-renderTable({df})
})
#We can change any input as much as we want, but the code wont run until the trigger
# input$Go is pressed.
observeEvent(input$Go, {
A<-input$Test_OE
B<-input$Test_OE2
C<-input$Test_OE3
df<-c(A,B,C)
output$Observe_Out_E<-renderTable({df})
})
}
shinyApp(ui, server)
reactive
Create a variable that can be changed over time by user inputs, evaluates "lazy" meaning only when called.
observe
Continually monitor reactive events and variables, whenever ANY reactive variable is changed in the environment (the observed environment), the code is evaluated. Can change values of previously defined reactive variables, cannot create/return variables.
observeEvent (Domino Effect)
Continually monitor ONE defined reactive variable/event (the trigger) and run the code when the the trigger is activated by change/input of that trigger. Can change values of previously defined reactive variables, cannot create/return variables.
eventReactive Create a variable, with a defined trigger similar to observeEvent. Use this when you want a reactive variable that evaluates due to a trigger instead of when it is called.
Feel free to edit to improve or correct this post.
There is already a very detailed answer, so I'll just add my own short simple two cents:
Whenever possible, stick to reactive() rather than reactiveValues(). Normal reactive() works more inline with shiny's reactive programming philosophy, meaning that the reactive() expression just tells shiny how the variable is calculated, without having to specify when. Shiny will take care of determining when to calculate it. They will get evaluated lazily (only when needed to), they will cache their value, they will work with the bookmarking feature - it's just the way shiny was designed and should always be the first choice.
With reactiveValues(), you are now back in more imperative programming territory, not reactive. There are cases where reactive() does not cut it and you need to use reactiveValues() (or reactiveVal()), but they should only be used if reactive() won't work. For example, with reactive() there is only one place where the variable is defined, so if you want to define the variable in multiple places, you'll need to use reactiveValues(). For a more complete explanation on the difference between reactive() and reactiveValues(), you can see my answer from an old post
observe() vs observeEvent(): you can think of them as the same thing, but observeEvent() is simply a shortcut for observe() that gets triggered by certain variables, and the rest of the code is isolate()-ed. In fact, anything you do with observeEvent() can always be done with observe() as well, it's two flavours of the same thing.

R Shiny: reactivevalues from function

I stored several tables in .rds files which I would like to import using readRDS in a Shiny session. Therefore I defined the following global function:
get.station <- function(sname){
file.name <- paste(sname".rds", sep="")
return(readRDS(file.name))
}
within the server function I define the reactive value:
st.reactive <- reactiveValues(get.station(input$station.sel))
where input$station.sel comes from the ui using selectInput(...). This results in the following error message:
Operation not allowed without an active reactive context.
(You tried to do something that can only be done from inside
a reactive expression or observer.)
This error message even does not disappear if I define this function using reactive():
get.station <- reactive({
file.name <- paste(input$station.sel".rds", sep="")
return(readRDS(file.name))
})
and within the server:
st.reactive <- reactiveValues(data=get.station())
Do you have any help?
You've got the right idea, just put the function inside a reactive or observe_ function. While you can define reactiveValues in the initial call, its best, in my opinion, to create the reactive values object empty and then do all your assignments with the <- notation.
The confusion comes from the fact that, despite it's name, reactiveValues is not a reactive expression. It generates a reactiveValues object that reactive values can be stored in, but it only runs once and does not check whether its values are invalidated.
In your case, I'd do the following:
rv <- reactiveValues()
rv$st.reactive <- observe({get.station(input$station.sel)})

Is it possible to have a Shiny ConditionalPanel whose condition is a global variable?

My goal is to have a tabsetPanel wrapped in a conditionalPanel whose condition is a global variable being false.
ui.R
mainPanel(
conditionalPanel("searchPage == \"false\"",
tabsetPanel(
tabPanel("Summary",htmlOutput("summary")),
tabPanel("Description", htmlOutput("description"))
))),
global.R
searchPage <- "true"
then in server.R I assign new values to it a few different times, but all like this:
observeEvent(input$openButton,
output$results <- renderUI({
textOutput("")
searchPage <- "false"
}))
No matter what I do, I always get "Uncaught ReferenceError: searchPage is not defined". I've tried changing the global.R to multiple different combinations of using quotes, not using quotes, using <- or <<-, making it this.searchPage, my.searchPage and numerous other things (of course always making server.R and ui.R match too), but haven't had much luck at all.
As mentioned in a comment on the question's post, this is a perfect usecase for the shinyjs toggle()/show()/hide() functions. Whenever you need to conditionally show something where the condition is not a simple javascript expression of an input, it's easy to use these functions instead of a conditionalPanel().
In order to use these functions, you need to have some way to specify the element you want to hide/show (in this case, the mainPanel()). The easist way to do this is to just wrap the entire panel in a div with an id. So define the panel like mainPanel(div(id = "mainpanel", ...)) and voila, there's an id to your panel, and now you can call shinyjs::show("mainpanel") or hide() whenever you want in the server code.
What you are trying to do is not really possible the way you are trying to do it (the server and client are in different environments and don't share variables). You will need to explicitly pass the value from server to client, and there are different approaches to doing that. One way:
library(shiny)
runApp(list(ui = fluidPage(
conditionalPanel(condition='output.bool',
HTML("Hello world")),
actionButton("btn","Press me to toggle")
),
server = function(input, output, session) {
value=TRUE
output$bool <- eventReactive(input$btn,{
value
})
outputOptions(output,"bool",suspendWhenHidden=FALSE)
observeEvent(input$btn,
value <<- !value
)
}))
There are probably better approaches. Hope this helps

R Shiny accessing a dynamic input

I am new to shiny, I have been stuck on this for quite a while and the things I tried and read so far held no fruits. I have a dropdown, where the user will choose a Question, then depending on the question, a drop down will be populated with the response numbers. After the user chooses the response number a map will be plotted. I have gone through the dynamic drop down list, that is done. But I cannot get access to the second user input, the response number, so I can select my data for the map accordingly. I feel like this is really simple I don't know why this does not work. I am getting this error:
Error in .getReactiveEnvironment()$currentContext() : Operation not
allowed without an active reactive context. (You tried to do something
that can only be done from inside a reactive expression or observer.)
My code is as follows, I have tentatively put in special cases and later I will expand to a general case with lists.
library(shiny)
runApp(list(
ui = shinyUI(pageWithSidebar(
headerPanel('Dialect Comparison'),
sidebarPanel(
selectInput('Question', 'Choose The Question', c('100. Do you cut or mow the lawn or grass?'='Q100',
'101. Do you pass in homework or hand in homework?'='Q101')),
uiOutput('C')
),
mainPanel(
plotOutput('plot')
)
)
),
server = function(input, output){
output$C = renderUI({
ques = input$Question
selectInput('Choice', 'Choose The Response', seq(0,max(ling_data[,ques])))
})
##########
#The Data#
##########
#text = renderPrint({'uhu'})
#print(text()) #THIS WORKS
choice_number = renderPrint({input$Choice}) #http://shiny.rstudio.com/gallery/dynamic-ui.html
print(choice_number()) #it fails here
...
})
}
))
Reactive variables, including inputs, can be accessed only in a reactive scope created using one of the following:
shiny::reactive, shiny::eventReactive
shiny::observe, shiny::observeEvent
shiny::render*
or inside shiny::isolate block.
For actions like logging you probably want observe block:
observe({print(choice_number())})

Can I save the old value of a reactive object when it changes?

Note: After coming up with the answer I reworded the question to make if clearer.
Sometimes in a shiny app. I want to make use of a value selected by the user for a widget, as well as the previous value selected for that same widget. This could apply to reactive values derived from user input, where I want the old and the new value.
The problem is that if I try to save the value of a widget, then the variable containing that value has to be reactive or it will not update every time the widget changes. But, if I save the the value in a reactive context it will always give me the current value, not the previous one.
How can I save the previous value of a widget, but still have it update every time the user changes the widget?
Is there a way that does not require the use of an actionButton every time the user changes things? Avoiding an actionButton can be desirable with adding one is otherwise unnecessary and creates excess clicking for the user.
Seeing as the session flush event method seems to be broken for this purpose, here is an alternative way to do it using an observeEvent construct and a reactive variable.
library(shiny)
ui <- fluidPage(
h1("Memory"),
sidebarLayout(
sidebarPanel(
numericInput("val", "Next Value", 10)
),
mainPanel(
verbatimTextOutput("curval"),
verbatimTextOutput("lstval")
)
)
)
server <- function(input,output,session) {
rv <- reactiveValues(lstval=0,curval=0)
observeEvent(input$val, {rv$lstval <- rv$curval; rv$curval <- input$val})
curre <- reactive({req(input$val); input$val; rv$curval})
lstre <- reactive({req(input$val); input$val; rv$lstval})
output$curval <- renderPrint({sprintf("cur:%d",curre())})
output$lstval <- renderPrint({sprintf("lst:%d",lstre())})
}
options(shiny.reactlog = TRUE)
shinyApp(ui, server)
Yielding:
Update This answer was posted before the advent of the reactiveValues/observeEvent model in shiny. I think that #MikeWise 's answer is the better way to do this.
After some playing around this is what I came up with. The ui.r is nothing special
ui.r
library(shiny)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
selectizeInput(inputId="XX", label="Choose a letter",choices=letters[1:5])
),
mainPanel(
textOutput("Current"),
textOutput("old")
)
)
))
"Current" will display the current selection and "old" displays the previous selection.
In the server.r I made use of three key functions: reactiveValues, isolate and session$onFlush.
server.r
library(shiny)
server <- function(input, output,session) {
Values<-reactiveValues(old="Start")
session$onFlush(once=FALSE, function(){
isolate({ Values$old<-input$XX })
})
output$Current <- renderText({paste("Current:",input$XX)})
output$old <- renderText({ paste("Old:",Values$old) })
}
The server.r works like this.
First, Values$old is created using the reactiveValues function. I gave it the value "Start" to make it clear what was happening on load up.
Then I added a session$onFlush function. Note that I have session as an argument in my server function. This will run every time that shiny flushes the reactive system - such as when the selectizeInput is changed by the user. What is important is that it will run before input$XX gets a new value - so the value has changed at the selectizeInput but not at XX.
Inside the session$onFlush I then assign the outgoing value of XX to Values$old. This is done inside an isolate() as this will prevent any problems with input$XX gets updated with the new values. I can then use input$XX and Values$old in the renderText() functions.

Resources