Addressing multiple inputs in shiny
You can use names on input :
grep(pattern = "d+[[:digit:]]", x = names(input), value = TRUE)
A working example :
library("shiny")
ui <- fluidPage(
fluidRow(
column(
width = 6,
lapply(
X = 1:6,
FUN = function(i) {
sliderInput(inputId = paste0("d", i), label = i, min = 0, max = 10, value = i)
}
)
),
column(
width = 6,
verbatimTextOutput(outputId = "test")
)
)
)
server <- function(input, output){
output$test <- renderPrint({
sapply(grep(pattern = "d+[[:digit:]]", x = names(input), value = TRUE), function(x) input[[x]])
})
}
shinyApp(ui = ui, server = server)
dplyr multiple inputs from Shiny
Principal == input$selectPrincipal | input$selectPrincipal == "All"
R Shiny - How to update a SINGLE input with Multiple input methods
Do you mean something like this?
ui <- fluidPage(
numericInput("year", "", min = 1979, max = 2017, value = 1979),
sliderInput("year2", "Select Year", min = 1979, max = 2017, value = 1979)
)
#===================================================
server <- function(input, output, session) {
observeEvent(input$year, {
updateSliderInput(session, "year2", value = input$year)
})
observeEvent(input$year2, {
updateNumericInput(session, "year", value = input$year2)
})
}
shinyApp(ui, server)
Multiple inputs to reactive value R Shiny
You could get rid of the inPath
reactive and just use values$inDir
instead.
With req()
you'll wait until values are available. Otherwise you'll get the same error (invalid 'path' argument).
The reactive
triggers right away, while the eventReactive
will wait until the given event occurs and the eventReactive is called.
And if(is.null(values$inDir)) return()
won't work correctly, as it will return NULL if values$inDir
is NULL, which is then passed to list.files
. And list.files(NULL)
gives the error: invalid 'path' argument
.
Replace it with req(values$inDir)
and you won't get that error.
And your example with 2 inPath
- eventReactive's won't work, as the first one will be overwritten by the second one, so input$button1
won't trigger anything.
library(shiny)
ui <- fluidPage(
actionButton("button1", "First Button"),
textInput("inText", "Input Text"),
actionButton("button2", "Second Button"),
textOutput("outText"),
textOutput("outFiles")
)
server <- function(input, output) {
values <- reactiveValues(inDir = NULL)
observeEvent(input$button1, {values$inDir <- tcltk::tk_choose.dir()})
observeEvent(input$button2, {values$inDir <- input$inText})
output$outText <- renderText(values$inDir)
fileList <- reactive({
req(values$inDir);
list.files(path=values$inDir)
})
output$outFiles <- renderPrint(fileList())
}
shinyApp(ui, server)
You could also use an eventReactive
for button1
and an observeEvent
for button2
, but note that you need an extra observe({ inPath() })
to make it work. I prefer the above solution, as it is more clear what's happening and also less code.
server <- function(input, output) {
values <- reactiveValues(inDir = NULL)
inPath = eventReactive(input$button1, {values$inDir <- tcltk::tk_choose.dir()})
observe({
inPath()
})
observeEvent(input$button2, {values$inDir <- input$inText})
output$outText <- renderText(values$inDir)
fileList <- reactive({
req(values$inDir);
list.files(path=values$inDir)
})
output$outFiles <- renderPrint(fileList())
}
And to illustrate why if(is.null(values$inDir)) return()
won't work, consider the following function:
test <- function() { if (TRUE) return() }
test()
Although the if-condition evaluates to TRUE, there is still gonna be a return value (in this case NULL), which will be passed on to the following functions and in your case list.files
, which will cause the error.
How to select multiple input case using if statement in Shiny?
input$att
is a vector with potentially two elements, but you're asking if it's equal to a vector of one element. replace the == with %in% (and switch the order):
if ("magnitude" %in% input$att & "depth" %in% input$app) ...
An alternative, probably better solution would be to replace the equal sign with identical
, which isn't vectorized:
if(identical(input$att,"magnitude")) {...}
else if(identical(input$att,"depth")) {...}
else if (identical(input$att, c("magnitude", "depth") | identical(input$att, c("depth","magnitude")) {...}
Update multiple shiny apps inputs with different input widget types
Unfortunately there is no generic updateInput
function in shiny
. It is still possible to build a wrapper that identifies a certain name to a certain input type, but that will also require to know which argument is allowed or no. For example, updateActionButton
doesn't have value
or choices
as an argument so we'll need numerous if statements.
A possible workaround is to take advantage of renderUI
and directly pass the stored values. The only downside is that some functions like SliderInput
throw an error when some arguments are NULL, so an if statement is needed to appoint a default value for the first time the app runs. Alternatively a mock app can be executed once to only fill the first values.
Code:
library(shiny)
library(shinyStore)
library(tidyverse)
ui <- fluidPage(
initStore("store", "shinyStore-ex1"),
uiOutput('ui_all'))
server <- function(input, output, session) {
output$ui_all <- renderUI({
tagList(
headerPanel("shinyStore Example"),
sidebarLayout(
sidebarPanel = sidebarPanel(
textInput(inputId = "Text1", label = "Enter some texts",value = input$store$Text1)
),
mainPanel = mainPanel(
fluidRow(
numericInput(inputId = "Number1", label = "Enter a number", value = input$store$Number1),
sliderInput(inputId = "Slider1", label = "Pick a number", min = 0, max = 100, value = if(is.null(input$store$Slider1)){50} else{input$store$Slider1}),
actionButton("save", "Save", icon("save")),
actionButton("clear", "Clear", icon("stop"))
)
)
))
})
input_nms <- map(c('Text', 'Number', 'Slider'), ~str_c(.x, 1:1)) %>%
reduce(c)
#or if every type of input is repeteated n different times.
# input_nms <- map2(c('Text', 'Number', 'Slider'), c(n1, n2, n3), ~str_c(.x, 1:.y)) %>%
# reduce(c)
observeEvent(input$save, {
input_nms %>%
walk(~updateStore(session = session, name = .x, value = isolate(input[[.x]])))
session$reload() #to force the UI to render again with the new values
})
observeEvent(input$clear, {
input_nms %>%
walk2(c(NA, NA, 50), ~updateStore(session = session, name = .x, value = .y))
})
}
shinyApp(ui, server)
R Shiny filter with two inputs
First of all, I refactored your code, since it was really hard to read for me. (I also merged the two files into app.R
, but it's not necessary)
Second: you use the wrong logical operator. There are two problems with using ||
in this case:
You need the and
&
,&&
operator, instead of the or|
,||
, since you want to filter by 2 conditions.The longer form evaluates left to right examining only the first element of each vector. This is not what you want, you need to check all elements of the vector if they are equal to the filtering condition.
So you'd write subset(data, data$country == input$countryIn & data$code == input$code)
, but it's still not gonna work since the default value of textInput
is an empty string (""
), which won't yield any results.
So there are two scenarios: When the data is only filtered by the code
, and another where both filters are in action. You could use an if
statement for this:
output$tbl <- renderTable( {
if(input$code == "") subset(data, data$country == input$countryIn)
else subset(data, data$country == input$countryIn & data$code == input$code)
})
Please note, that you may want to delay validation, since slowly typing into the textInput
field will refresh the table.
Complete code:
library(shiny)
id <- 1:6
country <- c("Germany", "UK", "USA", "Poland", "UK", "UK")
code <- c(255,124,234,751,124,326)
data <- data.frame(id, country, code)
ui <- fluidPage(
titlePanel("This is my website"),
sidebarLayout(
sidebarPanel(
uiOutput(outputId="country"),
textInput(inputId="code",label="writte code")),
mainPanel(tableOutput(outputId="tbl"))
)
)
server <- function(input,output) {
output$country <- renderUI( {
selectInput(inputId ="countryIn", label="Choose country", choices=unique(data$country))
})
output$tbl <- renderTable( {
if(input$code == "") subset(data, data$country == input$countryIn)
else subset(data, data$country == input$countryIn & data$code == input$code)
})
}
shinyApp(ui, server)
Related Topics
Separate a Column into 2 Columns at the Last Underscore in R
Installing "Rgl" Package in R, MAC Osx El Captian
Difference Between Backticks and Quotes in Aes Function in Ggplot
Add a Vector to All Rows of a Matrix
Warning: Replacing Previous Import 'Head' When Loading 'Utils' in R
Removing Text Containing Non-English Character
Subtract Every Column from Each Other Column in a R Data.Table
Randomly Sample Data Frame into 3 Groups in R
How to Merge Two Data Frames in R by a Common Column with Mismatched Date/Time Values
Categorical Scatter Plot with Mean Segments Using Ggplot2 in R
Do You Reassign == and != to Istrue( All.Equal() )
Axis Labels for Each Bar and Each Group in Bar Charts with Dodged Groups
R Error: Unknown Timezone with As.Posixct()
\Sexpr{} Special Latex Characters ($, &, %, # etc.) in .Rnw-File