Dependent Inputs in Shiny Application with R

Dependent inputs in Shiny application with R

An example of updateSliderInput in shiny rmd

---
title: "Dependent Inputs"
runtime: shiny
output:
html_document
---
```{r}
sliderInput("n", "n", min=0, max=100, value=1)
sliderInput("n2", "n2", min=0, max=100, value=1)

observe({
updateSliderInput(session, "n", min=input$n2-1, max=input$n2+1, value=input$n2)
})
```

R Shiny - Dynamically adding dependent inputs using insertUI

Below is a working code. The main problem was your ctn reactive value initialized to NULL, because NULL + 1 = numeric(0) and numeric(0) + 1 = numeric(0).

library(shiny)

ui <- fluidPage(
actionButton('add', 'Add'),
div(id = 'placeholder')
)

server <- function(input, output, session) {

ctn <- reactiveVal(0)
Id <- reactive({
function(id){
paste0(id, ctn())
}
})

observeEvent(input$add, {

ctn(ctn() + 1)

insertUI(
selector = '#placeholder',
ui = div(
id = Id()('div'),
selectInput(Id()('letter'), 'Letter:', LETTERS[1:2]),
uiOutput(Id()('input'))
)
)

})

observeEvent(ctn(), {
id <- Id()('input')
selection <- Id()('letter')
output[[id]] <- renderUI({
req(input[[Id()('letter')]])
switch(
input[[selection]],
'A' = textInput(Id()('text'), 'ENTER TEXT', ''),
'B' = numericInput(Id()('numeric'), 'ENTER NUMBER', '')
)
})
}, ignoreInit = TRUE)

}

How to create mutually dependent numeric Input in Shiny?

You need to do two main things:

  • First let your initial values stable, so either their sum should be 1 (0.333, 0.333, 0.334), or maybe let the initial values be empty, which will only work if you have some type of error escaping mechanism to allow NA or empty string to be an initial value. As I thought there should be in any case some validation that the input is numeric I chose to use the second option, which works well with the validation.

  • Second one way to get rid of these infinite loops of observing and changing the input, is to change one at a time, meaning:

    • if A is changed ---> change B,
    • if B is changed ---> change C, and
    • if C is changed ---> change A

That being said, note that the order of changing the input makes a difference in this approach, this is most noticeable at the start when you give the input their first set of values.

There might be a better approach to solve this, but this is what I can think of, so here it goes.

The UI:

library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Mutually Dependent Input Values"),
sidebarLayout(
sidebarPanel(
numericInput("A", "A", NA),
numericInput("B", "B", NA),
numericInput("C", "C", NA)
),
mainPanel(
verbatimTextOutput("result")
)
)
))

The Server:

server <- shinyServer(function(input, output, session) {
sum <- reactive({
validate(
need(is.numeric(input$A), 'A is not a number, only numbers are allowed'),
need(is.numeric(input$B), 'B is not a number, only numbers are allowed'),
need(is.numeric(input$C), 'C is not a number, only numbers are allowed')
)
input$A + input$B + input$C})

observeEvent(input$A,{
newB <- 1 - input$A - input$C
updateNumericInput(session, "B", value = newB)
})

observeEvent(input$B,{
newC <- 1 - input$B - input$A
updateNumericInput(session, "C", value = newC)
})

observeEvent(input$C,{
newA <- 1 - input$C - input$B
updateNumericInput(session, "A", value = newA)
})

output$result <- renderPrint({
print(sprintf("A=%.3f B=%.3f C=%.3f ----> A + B + C = %.0f",
input$A, input$B, input$C, sum()))
})
})

Run:

shinyApp(ui,server)

Dependent filter in shiny inputs

the problem comes from that you have your render UI codependent of the input variables and when one changes the whole UI rerendered including the values of the input variables. Fot this use-case you are better of with the update*Input functions. Here is a working version for your example

library(shiny)
library(shinydashboard)
library(shinyWidgets)
##
ui <- shinyUI({
sidebarPanel(

htmlOutput("brand_selector"),
htmlOutput("candy_selector"))

})
##
server <- shinyServer(function(input, output,session) {
candyData <- read.table(
text = "Brand Candy
Nestle 100Grand
Netle Butterfinger
Nestle Crunch
Hershey's KitKat
Hershey's Reeses
Hershey's Mounds
Mars Snickers
Mars Twix
Mars M&Ms",
header = TRUE,
stringsAsFactors = FALSE)
observeEvent({
input$candy
},
{
available2 <- candyData
if(NROW(input$candy) > 0 ) available2 <- candyData[candyData$Candy %in% input$candy, ]
updatePickerInput(
session = session,
inputId = "brand",
choices = as.character(unique(available2$Brand)),
selected = input$brand
)
},
ignoreInit = FALSE,
ignoreNULL = FALSE)
output$brand_selector <- renderUI({

pickerInput(
inputId = "brand",
label = "Brand:",
choices = NULL,
multiple = T,options = list(`actions-box` = TRUE))

})
observeEvent({
input$brand
},{
available <- candyData
if(NROW(input$brand > 0)) available <- candyData[candyData$Brand %in% input$brand, ]
updatePickerInput(
session = session,
inputId = "candy",
choices = unique(available$Candy),
selected = input$candy
)
},
ignoreInit = FALSE,
ignoreNULL = FALSE)
output$candy_selector <- renderUI({

pickerInput(
inputId = "candy",
label = "Candy:",
choices = NULL,
multiple = T,options = list(`actions-box` = TRUE))

})

})
##
shinyApp(ui = ui, server = server)

Connect mutually dependent shiny input values

There are a few ways to do this, here is one way:

library(shiny)
u <- shinyUI(fluidPage(
titlePanel("Mutually Dependent Input Values"),
sidebarLayout(
sidebarPanel(
numericInput("X", "X",2000),
numericInput("P", "P",1),
numericInput("C", "C",1000)
),
mainPanel(
verbatimTextOutput("result")
)
)
))
s <- shinyServer(function(input, output,session) {

observeEvent(input$P,{
newX <- input$P*input$C + input$C
updateNumericInput(session, "X", value = newX)
})
observeEvent(input$X,{
newP <- (input$X - input$C)/input$C
updateNumericInput(session, "P", value = newP)
})
output$result<-renderPrint({
val <- input$P*input$C + input$C
print(sprintf("X:%.0f P:%.0f C:%.0f - P*C + C:%.0f",input$X,input$P,input$C,val))
})
})
shinyApp(u,s)

Yielding:

Sample Image

Not sure this is the best way, it occilates if you start out in a state that is inconsistent - need to think about how to suppress this.

Shiny modal that is dependent on fileInput() in shiny app

Perhaps you can try with an if condition.

observeEvent(input$file1, {
if (is.null(input$file1))
# Show a modal when the button is pressed
shinyalert("Oops!", "Something went wrong.", type = "error")
}, ignoreNULL = FALSE)

Shiny: in search of simple selectInput dependency solution

Thanks to Ben for pointing me in the right direction (see link in his comment). I basically needed to change the second selectInput statement in the ui to:

selectInput("countyin", "Select County", choices = NULL)

and then add an observe statement in the server to make the selections reactive:

observe({
updateSelectInput(session, "countyin", "Select County",
choices = usdata[usdata$state == input$statein,]$county)
})


Related Topics



Leave a reply



Submit