So this is somehow a follow up to my previous: Automatic GUI Generating in R Shiny wher I posted the solution to how to generate elements iteratively.
Now I am unable to recieve/check which actionbuttons have been pressed and perform some action upon press.
In general, there is a function that generates the buttons and sends it to the ui.R:
output$generateImages <- renderUI({
(...)
i <-1
for(dir in folders){
(...)
txt<-paste0("rep",i)
pp<-pathNameToImage
LL[[i]] <- list(actionButton(txt,icon=imageOutput(pp,width="100px",height="100px"),label=dir))
i<-i+1
}
return(LL)
}
in ui.R I have:
uiOutput('generateImages')
And it displays the buttons fine by accumulating them into the list called "LL".
I have tried looking for tutorials and examples but was not able to find how it is done with images, and how to later recieve input from buttons that were not created "by hand", but iteratively.
How do I access these buttons in "observe" so that I can perform a action? I have tried input$generateImages, input$LL and few others, but all of them had a value of NULL.
You'll need to access them by their unique ID. The first argument passed to actionButton is its ID. That's what you'll need to use to get it as input.
So:
LL[[i]] <- list(actionButton("SomeID"))
when you assign it, then
input[["SomeID"]]
when you want to reference it. Of course, you can use a variable instead of a hardcoded string for the ID.
Related
I have the following issue with the behaviour of R shiny's numeric input behaviour. Consider the following snippet:
ui <- basicPage(
numericInput("example","Example",value=0),
verbatimTextOutput("changelog")
)
server <- function(input,output){
output$changelog <- renderPrint(input$example)
}
shinyApp(ui,server)
Suppose that I want to update the example input field to 12345. My issue is that the default event listener would react to every keystroke. Thus the input field would be set to 1, 12,123 and 1234 before I finally get the desired value of 12345. Each numeric input set would be followed by an expensive computation - so this is a very undesirable behaviour.
What I am after is modifying this behaviour so that the event listener only reacts to the numeric input when the user hits enter or leaves the input field. I have currently two approaches to this:
Use a reactiveValue with an update actionButton so that the input is updated only when the user clicks update. I find this an inelegant solution and only shirks the original problem without solving it.
Modify the local shiny.js file directly and remove the keyup.textInputBinding event. That creates another issue with running the shiny app on other computers and it would make this modified behaviour uniform for all numericInput.
I'm wondering if anyone has a solution/suggestion to this? Preferably something that does not involve changing the local shiny.js file. I'm guessing a solution would involve using shinyjs::runjs to manually unsubscribe the keyup.textInputBinding event - but I don't know enough JavaScript to execute it.
You can slow frequent invalidation down with debounce or throttle. In your case, my first guess would be debounce: Debouncing means that invalidation is held off for millis milliseconds.
The reactive expression will only be validated until that time window has passed without a subsequent invalidation which may have an effect like this: ooo-oo-oo---- => -----------o-
In your case:
library(shiny)
ui <- basicPage(
numericInput("example","Example",value=0),
verbatimTextOutput("changelogImmediate"),
verbatimTextOutput("changelog")
)
server <- function(input,output){
exampleInput <- reactive(input$example) %>% debounce(1000)
# debouncedExampleInput <- exampleInput
output$changelogImmediate <- renderPrint(input$example)
output$changelog <- renderPrint(exampleInput())
}
shinyApp(ui,server)
Hello I have a shiny app that should read a list of configurations from a database and prompt the user with the list of configurations.
The list depends on some GET parameters, according to them the list can be different.
I tried two approaches:
in ui.R I put only one big uiOutput element and inside it's implementation (in server.R) I will do an lapply and foreach configuration I will output a fluidRow with some elements in it.
ui.R:
uiOutput("serversList")
server.R:
output$serversList <- renderUI({
lapply( get.servers()$server, function(servName) {...
in ui.R I put an lapply based on the list that comes from the database, and for each configuration I will output a fluidRow with new output objects. In server.R I put another lapply based on the same list that comes from the database, and for each configuration i will define the implementation of each output object dynamically defined in ui.R
ui.R
fluidRow(
box(width=12,
lapply(get.servers()$server, function(serv) {...
list(
uiOutput(paste0('conf', serv)),...
server.R
lapply(get.servers()$server, function(servName) {
output[[paste0('conf', servName)]] <- renderUI({...
solution 1 works, but every time that I change some configuration the whole list of configurations is refreshed, and the values set by the user were lost.
I need a way to control what object should be updated when.
solution 2 doesn't work if I fetch data from a database (in server.R).
If instead I fetch the data from a plain text file in global.R, solution 2 works and I can control what object should be updated when, because each output object is refreshed when the input objects used inside it changes.
Is there any solution 3? Or 1/2 can be fixed?
I found the solution.
I can fix solution 1, and inside renderUI for serversList
I can define other renderUIs, return a fluidRow with uiOutput connected with the renderUIs.
Long story made short: nest solution 2 inside solution 1.
Previously, I had built a shiny dashboard with chart outputs that worked just fine and looked like the following:
output$someName <- renderGvis({
input$inputButton
data <- isolate(myData(function here))
donut <- gvisDonut({...})
return(donut)
})
Since the addition of observeEvent and eventReactive, I've not been able to get it to work the same as before. Essentially, the output$someName is a chart that is dependent on multiple inputs, and each time the user clicks on the inputButton, I need renderGvis to re-evaluate. The function should NOT re-evaluate when any of the other inputs change, just when the button is pressed.
I've had some luck getting observeEvent to run on input$inputButton click, however, each time I change any of my input parameters, the query is quickly rerun without having to press the button. Any takers here?
More detailed below:
output$someName <- renderGvis({
input$inputButton
data <- isolate(dataGrabber({})) # function that takes input and returns data frame using RMySQL
isolate(simpleChart(data = data)) # simpleChart is a function to produce a gvisCalendar chart.
OK...found an answer to this if anyone ever has this problem. The issue, which for some reason I had not encountered in the past, is that the isolate function now runs regardless of whether or not the value for actionButton is 0 or not. I believe in the past, it wouldn't run until actionButton had a value greater than 0.
The simple fix was:
output$someName <- renderGvis({
input$inputButton
if (input$inputButton == 0)
return()
isolate({ code to isolate})
})
I am new to R Shiny and I am trying to create an app which I need it to be as interactive as possible. One problem that I am dealing with is this. In the ui.R I have the following:
helpText("Select a feature"),
uiOutput("sliders")
And in the server.R:
output$sliders <- renderUI({
selectInput('feature_name',
'Feature name', #Description
choice = c("F1"='1', "F2"='2'))
})
My question is that is it possible to change something in renderUI so that instead of setting c("F1"='1', "F2"='2')) statically I can pass the results of a function to it so it can be more dynamic (a function which generates a feature list based on something that user does and passes the list to renderUI to create the selectInput). Something like following:
output$sliders <- renderUI({
selectInput('feature_name',
'Feature name', #Description
choice = c(feature_creator(method)))
})
Where "feature_creator" is a function and it returns: "F1"='1', "F2"='2' based on the method selected by user (variable "method" is defined and I have the value). My question to be more specific is what should "feature_creator" return as output?
Hope my question is clear enough. Let me know if I should add anything to the problem description.
Any help will be much appreciated. Thanks
Assuming that all you really need is the method argument, this is not hard.
1) Make a radioButtons() input in your ui that will let the user select a method, lets give it inputId="MethodChoice".
2) In your choice argument in the selectInput you should use choice=c(feature_creator(input$MethodChoice))
Then feature_creator will get a text value based on the method the user chooses.
In order to work in choice, feature_creator should return a named list, similar in format to what you hard-coded.
I have a R shiny application in which I have drop down box defined in ui.R as lib whose values are c("X","Y","Z") and also a check box called spcheck which is defined as
checkboxInput("spcheck","label1",value = FALSE))
Other conditions makes this checkbox available only when input$lib=Z and checking it would make few things appear.
When users select a different library, say X, I want to make the spcheck value FALSE, So I added the following code to server.R
observe({
if (input$lib %in% c("X","Y") )
{cat("uncheck called 1 : ",input$spcheck,'\n')
updateCheckboxInput(session,"spcheck","label1,value = FALSE)
cat("uncheck called 2 : ",input$spcheck,'\n')
}
else return()
})
The text displayed at console is :
uncheck called 1 : TRUE
uncheck called 2 : TRUE
Why is it not making the spcheck value FALSE?
May be I'm missing something very trivial, but I couldn't figure it out.
Any help??
Because it takes a few milliseconds since you tell shiny to update the input until it actually happens. When you call the update method, shiny has to send a message to JavaScript to change the value of the input, and once that's done, JavaScript sends a message back to R saying that the input has a new value. But the input variable does not change instantly when you make the call, it'll only have an updated value next time a reactive statement uses the input$spcheck variable