I've built a Shiny dashboard app that shows a number of metrics data of scientific articles by university School. The app is at https://ttso.shinyapps.io/2amconf and the code https://gist.github.com/tts/900b4e27bf37e8969ebd with some sample data of file dataforcharts.csv which is the data source of my question here.
My problem is the NVD3 chart on the landing tab.
At first it draws OK the selected max 2 items (=articles) from the chosen School, which is All at the beginning. But whenever I select some School - and selectizeInput then updates the list of items of that School - nothing happens.
I've tried to debug what's going on.
validate(
need(!is.null(itemsData()), "Please select some items")
)
dataC <- itemsData()
browser()
When the execution stops there, I can see that dataC do contains the chosen data.
Console utput of options(shiny.trace=TRUE) is talkative but I cannot really understand what it tries to tell me. Here's a snippet from the last message when the chart ought to render with new data, but does not.
SEND {"errors":[],"values":{"chart":"<style>.rChart {width: 800px;
height: 400px} </style>\n<script type='text/javascript'>\n
$(document).ready(function(){\n drawchart()\n });\n
function drawchart(){ \n var opts = {\n \"dom\":
\"chart\",\n\"width\": 800,\n\"height\": 400,\n\"x\":
\"id\",\n\"y\": \"value\",\n\"group\": \"variable\",\n\"type\":
\"multiBarChart\",\n\"id\": \"chart\" \n},\n data =
[ TEXT CUT OFF ] drawchart(){ \n n return chart;\n
});\n };\n</script>"},"inputMessages":[]}
Again, data= includes the correct, chosen data.
Is something wrong with my reactive values?
EDIT after observation: if I delete all selected item(s) before switching to another School, this works.
So, after some trial & error, this looks promising:
itemsData <- reactive({
if( is.null(input$items) ){
return(NULL)
}
isolate(selectedSchoolData()[selectedSchoolData()$Title %in%
input$items, ])
})
but I haven't yet got my head over isolate() so if someone could explain, why this works, I'd be grateful.
I decided to go with this.
itemsData <- reactive({
if( is.null(input$items) ){
return(NULL)
}
isolate(selectedSchoolData()[selectedSchoolData()$Title %in%
input$items, ])
})
Related
I am trying to write an input page that takes the date of a section's last training, then calculates the currency of that training (how many days since), but I seem to be having a problem accessing the date from the dateInput element. I'm currently just trying to get it to print, but it is eluding me. Is there something I'm missing, or how can I get this to work? I've commented out the code to (hopefully) calculate the date gap, as I haven't had a date to work through that just yet. If you see an issue there, I'd appreciate that pointer as well.
Thank you!
library(shiny)
ui <- fluidPage(
tags$h3("Section Training"),
dateInput("section_Last_Training",
"When was your last training course?",
daysofweekdisabled = c(0, 6),
max = Sys.Date()
),
)
server <- function(input, output, session) {
section_Last_Training <- reactive({
# dateGap = as.character(difftime(Sys.time(), input$section_Last_Training, units = "days"))
print(input$section_Last_Training)
})
}
shinyApp(ui, server)
It is working, just make sure the last value in reactive is the value you want to assign to the reactive. You can do print, but do it before your gap calculation. Another thing is reactive is "lazily" evaluated. It means if there is no downstream reactivity requires it, it will not be calculated. So you need to add some events that require this reactive to make it work. See the code below.
library(shiny)
ui <- fluidPage(
tags$h3("Section Training"),
dateInput("section_Last_Training",
"When was your last training course?",
daysofweekdisabled = c(0, 6),
max = Sys.Date()
),
)
server <- function(input, output, session) {
section_Last_Training <- reactive({
print(input$section_Last_Training)
as.character(difftime(Sys.time(), input$section_Last_Training, units = "days"))
})
observe(print(section_Last_Training()))
}
shinyApp(ui, server)
I am developing a simple web app using the Interactive Document approach with R_Markdown and Shiny. I have a series of input UI objects that get the user options, each of these modifies the next in a chain, and the final one triggers the output (a chart). So I have
A map, which when clicked defines the
Seasons of data available, when one is selected it gives the
Soil types in the data, when one or more are selected it gives the
Elevation classes in the data, when one is selected we then calculate and draw the
Output chart of the selected data.
So for example there are drop down lists to choose the season and soil(s):
output$season_selector <- renderUI({
cat(file=stderr(), paste("render season selector"), "\n")
selectInput("season", h4("Season?"), my$season_here, selected=my$season_sel)
})
output$soil_selector <- renderUI({
cat(file=stderr(), paste("render soil selector"), "\n")
selectInput("soil", h4("Soils?"), my$soil_here, selected=my$soil_sel,
selectize=FALSE, multiple=TRUE)
})
I observe input$season, and this triggers an update of the "soil" UI element.
observeEvent(input$season, {
...
# reset soil list and default soil selected
my$soil_sel <- my$soil_here
updateSelectInput(session, "soil", choices=my$soil_here, selected=my$soil_sel)
})
However, this does invalidate input$soil (although the UI element options and selection have changed, the user has not made a selection), and so the next step in the cascade doesn't trigger:
observeEvent(input$soil, {
...
# reset elev list and default elev selected
my$soil_sel <- my$soil_here
updateSelectInput(session, "soil", choices=my$soil_here, selected=my$soil_sel)
})
How do I achieve a cascade of reactive UI elements like this? Each reaction needs to trigger either when the UI options and selection changes or when the user makes a different selection. Thanks.
Ok, I think I've fixed it. I needed to use the following pattern, which resets variables further down the chain, and doesn't respond to user inputs unless the value has changed. This avoids duplicate or missing events.
# reset selections
my$soil_default <- my$soil_here
my$soil <- my$soil_default
my$elev <- list(NA)
}) # end reaction to season changing
observeEvent(input$soil, {
req(input$soil, input$soil!="NA")
if (any(my$soil != input$soil)) {
my$soil <- input$soil
my$elev <- list(NA)
}
})
#### react to change of soil ####
observeEvent(my$soil, {
cat(file=stderr(), "\n")
cat(file=stderr(), paste("change of my$soil = "))
cat(file=stderr(), paste(my$soil), "\n")
req(my$soil, my$soil!="NA")
I am trying to build a small shiny app, which I would like to save as a function (The method is explained here)
While the app works fine, I am facing a strange problem. My app renders a plot (among a few other output). However, the plot is not always rendered on the Browser. At times, the plot is displayed on the R Studio's output pane. And the behavior appears to be fairly random (i.e. at times it works with the plot correctly getting displayed on the browser whereas often times the output just gets plotted on R Studio)
I am giving a very simplified version of my code below retaining the key elements and structure of the app:
sampleApp <- function(input_data,y){
require(shiny)
shinyApp(
ui = fluidPage(
sidebarLayout(
sidebarPanel(uiOutput("variables"),
selectInput........#add other input widgets
mainPanel(plotOutput("plot_output"),
dataTableOutput...#few other output
)
),
server = function(input, output) {
funcA <- reactive({
#Generates a formula expression basis user inputs
})
fun_plot <- reactive({
#Generates a plot output, calls funcA in the process
})
event_output <- eventReactive(input$ActButton,{
# I have an action button..The plot (and other output) gets updated
# when the button is clicked..
})
output$plot_output <- renderPlot({
event_output()$plot_output
})
# other render output functions
}
)
}
Any inputs/guidance will be greatly appreciated!
Thanks
I am producing a Shiny App that produces a leaflet (rCharts) map depending on which bus route you pick. Everything renders perfectly at first glimpse, but if you change the route number, an empty map appears (not even a tilelayer). This isn't specific to the route number. For example, I can pick any route number to produce the first plot successfully, whereas the second plot, regardless of route number, is blank.
Has anyone come across this before? Is there a workaround?
Here is a simple example.
ui.R:
library(shiny)
library(rCharts)
shinyUI(fluidPage(
titlePanel("Responsive Leaflet Map using rCharts"),
sidebarLayout(
sidebarPanel( "",
selectInput(
'route', 'Pick a bus route:',
choices = as.character(c("232","229"),
selectize = FALSE)
)
),
mainPanel("",
chartOutput('map', 'leaflet')
)
)
))
server.R:
library(shiny)
library(rCharts)
library(RJSONIO)
library(rgdal)
shinyServer(function(input, output) {
output$map <- renderMap({
filename <- paste('json/',input$route,'.geojson',sep='')
json <- fromJSON(file = filename)
map3 <- Leaflet$new()
map3$tileLayer(provide='Esri.WorldTopoMap')
map3$setView(c(49.2494,-122.9797), zoom = 10)
map3$set(dom = 'map')
map3$fullScreen(TRUE)
map3$geoJson(
json,
style = "#!
{color: '#c93312'}!#")
map3
})
})
Thanks so much for any help you are able to provide.
C
The trick is to remove map3$set(dom = 'map'). Problem solved!
I am trying to develop a very basic shiny app. The ui script is very simple
shinyUI(fluidPage(
titlePanel("Drawing a Dice"),
sidebarLayout(
sidebarPanel(
actionButton("action", label = "Draw"),
),
mainPanel(
textOutput("text1")
)
)
))
But i am not sure how to go about doing the server. R
I need the server.R to do the following: Every time the user clicks on draw,it draws a random number from 1:6 and fills the 1st cell of a 10 cell array. And for every click on done till 10 ,it repeats the job. The eventual outcome will be a length 10 vector with random numbers between 1 to 6. In need to give the user an option of exiting by clicking on finish. But i need to be able to retrieve the final resultant vector after closing the app.
Hence the server.R needs to perform the following operation in a one step increments
draw<-function(){
Dice<-c(1:6)
Mydraws<-numeric(10)
for(i in 1:10){
x<-sample(Dice,1,replace=TRUE)
Mydraws[i]=x
}
Mydraws
}
Hence ,i should be able to fetch the Mydraws vector even after user exits by clicking on finish(not included in ui.R)
I do not even know if its possible in shiny.
Here is one way to do it:
server.R
numbers <- list()
shinyServer(function(input, output)
{
output$array <- renderText({
# the presence of input$action will cause this to be evaluated each time the button is clicked
# the value gets incremented each time you click it, which is why we use it as the index of the list
random_number <- sample(1:6,1)
# add to the global variable
numbers[input$action] <<- random_number
return(random_number)
})
})