I need to update/reverse two inputs from drop down inputs upon a button press. At the moment when I hit the swap button (reverse_xz), it reacts however the updatePickerInput doesn't switch my x and z inputs.
I wanted to have the functionality where, once the swap button is clicked, switch the already selected pickerInputs. Then, all the drop down choices (including the selected) need to get reversed. The reason we have to remove the selected choices from vector is to prevent duplicate selections in both x and z inputs.
I am not sure if I have to render the pickerInput ui on the server side?!
This is my code below:
#global.R
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(shinyjs)
#variable labels
my_vars <- c("None"= "NONE",
"All" = "all_all",
"Pro" = "Pro_",
"Locomania" = "locomania_Type",
"Racer" = "race")
#ui.R
ui <- shinydashboardPlus::dashboardPage(
header = shinydashboardPlus::dashboardHeader( ),
body = shinydashboard::dashboardBody( box(textOutput("inputs") ) ),
sidebar = shinydashboardPlus::dashboardSidebar(
shinyWidgets::pickerInput(
inputId = "xvar",
label = "X Axis: ",
choices = my_vars,
options = list(
size = 5),
multiple = FALSE,
selected = "all_all"
),
# Button to reverse the choices
shiny::fluidRow(
shiny::column(12, offset = 4,
shinyWidgets::actionBttn(
inputId = "reverse_xz",
label = "",
style = "simple",
color = "primary",
icon = icon("retweet")
)
)
),
shinyWidgets::pickerInput(
inputId = "zvar",
label = "Z Axis: ",
choices = my_vars,
options = list(
size = 5),
multiple = FALSE,
selected = "race"
)
)
)
#server.R
server <- function(input, output, session) {
#
observe({
if(!is.null(input$reverse_xz))
shinyWidgets::updatePickerInput(session, "zvar",
choices = my_vars[!(my_vars %in% input$xvar)],
selected = isolate(input$zvar) )
shinyWidgets::updatePickerInput(session, "xvar",
choices = my_vars[!(my_vars %in% input$zvar)],
selected = isolate(input$xvar) )
})
# These observers remove the selected choices so both pickers are unique
observe({
if(!is.null(input$zvar))
shinyWidgets::updatePickerInput(session, "xvar",
choices = my_vars[!(my_vars %in% input$zvar)],
selected = isolate(input$xvar) )
})
observe({
if(!is.null(input$xvar))
shinyWidgets::updatePickerInput(session, "zvar",
choices = my_vars[!(my_vars %in% input$xvar)],
selected = isolate(input$zvar) )
})
# output inputs
output$inputs <- renderText({ paste0("x var: ", input$xvar,
"\n\n\n z var:", input$zvar,
"\n\n\nreverse press: ", input$reverse_xz) })
}
shiny::shinyApp(ui= ui, server= server)
Thank you in advance. I have looked at some relavant posts however they couldn't guide me much:
Updatepickerinput with change in pickerinput in Shiny
updatePickerInput not updating values after changing tabs in R shiny
update pickerInput by using updatePickerInput in shiny
Look at this and check if it would be OK for you:
#global.R
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(shinyjs)
#variable labels
my_vars <- c("None"= "NONE",
"All" = "all_all",
"Pro" = "Pro_",
"Locomania" = "locomania_Type",
"Racer" = "race")
#ui.R
ui <- shinydashboardPlus::dashboardPage(
header = shinydashboardPlus::dashboardHeader( ),
body = shinydashboard::dashboardBody( box(textOutput("inputs") ) ),
sidebar = shinydashboardPlus::dashboardSidebar(
shinyWidgets::pickerInput(
inputId = "xvar",
label = "X Axis: ",
choices = my_vars,
options = list(
size = 5),
multiple = FALSE,
selected = "all_all"
),
# Button to reverse the choices
shiny::fluidRow(
shiny::column(12, offset = 4,
shinyWidgets::actionBttn(
inputId = "reverse_xz",
label = "",
style = "simple",
color = "primary",
icon = icon("retweet")
)
)
),
shinyWidgets::pickerInput(
inputId = "zvar",
label = "Z Axis: ",
choices = my_vars,
options = list(
size = 5),
multiple = FALSE,
selected = "race"
)
)
)
#server.R
server <- function(input, output, session) {
#
observeEvent(input$reverse_xz, {
shinyWidgets::updatePickerInput(session, "zvar",
choices = my_vars[!(my_vars %in% input$zvar)],
selected = input$xvar)
shinyWidgets::updatePickerInput(session, "xvar",
choices = my_vars[!(my_vars %in% input$xvar)],
selected = input$zvar)
})
observe({
if (input$xvar == input$zvar && (length(input$zvar) > 0 && length(input$xvar) > 0)) {
shinyWidgets::updatePickerInput(session, "zvar",
selected = "")
shinyWidgets::updatePickerInput(session, "xvar",
selected = "")
}
})
# output inputs
output$inputs <- renderText({ paste0("x var: ", input$xvar,
"\n\n\n z var:", input$zvar,
"\n\n\nreverse press: ", input$reverse_xz) })
}
shiny::shinyApp(ui= ui, server= server)
I think that maybe this needs an explanation:
if (input$xvar == input$zvar && (length(input$zvar) > 0 && length(input$xvar) > 0))
So, when user choose two the same inputs, then we are updating pickerInputs, so both will have "Nothing selected" as a sign for user that something goes wrong (or that she/he did something wrong). However, "Nothing selected" is like NULL and we can't use NULL like this NULL == "something" inside if, so I'm checking if some input is NULL using length(input$) > 0, because length of NULL is 0. Instead of length(input$) > 0 you could use !is.null(input$) and maybe you should as it is probably more readable, but I'm leaving this decision for you.
Related
This is a follow-up to this Dynamic change in vtree within shiny: How to deselect
With this code below, I try to switch the arguments prunesmaller and prunebigger of the vtree package. I am quite sure to do this with an if else but I am not able to fix it:
In general I want to know how to tweak any argument of any function depending on a radiobutton in r shiny:
Here is my code so far:
library(shiny)
library(vtree)
# Define UI ----
ui <- pageWithSidebar(
# App title ----
headerPanel("Cyl vtree"),
# Sidebar panel for inputs ----
sidebarPanel(
radioButtons("smaller_bigger", h3("Prune smaller or bigger?"), choices = c("smaller", "bigger"), inline = TRUE),
sliderInput(inputId = "prune", label = "Number to prune?", step = 10, min = 0, max = 100, value = 0),
selectizeInput("level", label = "Level", choices = NULL, multiple=TRUE),
# This line is the only change from the original code
selectizeInput("values", label= "Values", choices = NULL, multiple=TRUE),
),
# Main panel for displaying outputs ----
mainPanel(
vtreeOutput("VTREE")
)
)
# Define server logic to plot ----
server <- function(input, output,session) {
df <- reactiveVal(mtcars)
vector <- c("cyl","vs", "am","gear")
observe({
updateSelectizeInput(session, "level", choices = colnames(df()[vector]), selected = NULL)
updateSelectizeInput(session, "values", choices = unique(df()$cyl))
})
output[["VTREE"]] <- renderVtree({
vtree(df(), c(input$level),
sameline = TRUE,
follow=list(cyl=input$values),
if(input$smaller_bigger=="smaller"){
prunesmaller = input$prune
} else
(input$smaller_bigger == "bigger"){
prunebigger = input$prune
}
)
})
}
shinyApp(ui, server)
In essence I try to handle this part of the code:
if(input$smaller_bigger=="smaller"){
prunesmaller = input$prune
} else
(input$smaller_bigger == "bigger"){
prunebigger = input$prune
}
)
It should do:
If radiobutton smaller is choosen then the argument should be prunesmaller == input$prune (where input$prune comes from the sliderinput)
If I replace the if else part by prunesmaller = input$prune the code works but only with prunesmaller:
The way you use the if will not work to set the functions argument. Instead use a single if for each argument, e.g. prunesmaller = if (input$smaller_bigger == "smaller") input$prune.
Note: Maybe I missed something, but I got an error when trying to set prunebigger and according to the docs there is no prunebigger argument.
library(shiny)
library(vtree)
# Define UI ----
ui <- pageWithSidebar(
# App title ----
headerPanel("Cyl vtree"),
# Sidebar panel for inputs ----
sidebarPanel(
radioButtons("smaller_bigger", h3("Prune smaller or bigger?"), choices = c("smaller", "bigger"), inline = TRUE),
sliderInput(inputId = "prune", label = "Number to prune?", step = 10, min = 0, max = 100, value = 0),
selectizeInput("level", label = "Level", choices = NULL, multiple = TRUE),
# This line is the only change from the original code
selectizeInput("values", label = "Values", choices = NULL, multiple = TRUE),
),
# Main panel for displaying outputs ----
mainPanel(
vtreeOutput("VTREE")
)
)
# Define server logic to plot ----
server <- function(input, output, session) {
df <- reactiveVal(mtcars)
vector <- c("cyl", "vs", "am", "gear")
observe({
updateSelectizeInput(session, "level", choices = colnames(df()[vector]), selected = NULL)
updateSelectizeInput(session, "values", choices = unique(df()$cyl))
})
output[["VTREE"]] <- renderVtree({
vtree(df(), c(input$level),
sameline = TRUE,
follow = list(cyl = input$values),
prunesmaller = if (input$smaller_bigger == "smaller") input$prune
#prunebigger = if (input$smaller_bigger == "bigger") input$prune
)
})
}
shinyApp(ui, server)
I am currently developing a Shiny app.
I would like to use multiple Picker Inputs to branch the processing flow.
Specifically, I would like to build the processing flow shown in the figure below.
For example
When Option1 is selected in PickerInput1
→ PickerInput2 displays the vector of Middle Class.
→ Set the Multiple option of PickerInput2 to False to make it a single selection.
→ Turn off Numeric Input so that you cannot enter numbers.
(Make it gray out or hide it on the UI in the first place)
→ Press the button to display "expression1".
When Option2 is selected in PickerInput1
→ PickerInput2 displays the vector of Middle Class.
→ Set the Multiple option of PickerInput2 to False to make it a single selection.
→ Turn on Numeric Input so that you cannot enter numbers.
→ Press the button to display "expression1".
When Option3 is selected in PickerInput1
→ PickerInput2 displays the vector of Middle Class and Major Class.
→ Set the Multiple option of PickerInput2 to True to select multiple options.
→ Turn off Numeric Input so that you cannot enter numbers.
→ Press the button to display "expression2".
When Option4 is selected in PickerInput1
→ PickerInput2 displays the MajorClass vector.
→ Set the Multiple option of PickerInput2 to True to select multiple options.
→ Turn off Numeric Input so that you cannot enter numbers.
→ Press the button to display "expression2".
Is it possible to branch the processing flow in this way?
I especially want to hear
・ Is it possible to change the Mutiple settings?
(Maybe I will use updatePickerInput, but can I change it with that function?)
・ Can Numeric Input be switched ON / OFF?
The sample code is below.
library("shiny")
library("shinyWidgets")
major_class <- c("A1","A2","A3")
middle_class <- c("A1_1","A1_2","A2_1","A2_2","A3_1","A3_2")
ui <- fluidPage(
fluidRow(
column(
width = 2, offset = 1,
pickerInput(
inputId = "p1",
label = "PickerInput1",
choices = c("Option1","Option2","Option3","Option4"),
options = list(
`live-Search` = TRUE,
`actions-box` = TRUE,
size = 7,
`selected-text-format` = "count > 3"
),
multiple =FALSE
)
),
column(
width = 2,
pickerInput(
inputId = "p2",
label = "PickerInput2",
choices = "",
options = list(
`live-Search` = TRUE,
`actions-box` = TRUE,
size = 7,
`selected-text-format` = "count > 3"
),
multiple =TRUE
),
numericInput("num", label = "Numeric input", value = 1)
),
column(
width = 2,
actionButton("p3","finish")
),
textOutput("resule_message")
)
)
server <- function(input, output, session) {
observeEvent(input$p1 ,{
if(input$p1 %in% c("Option1","Option2")){
updatePickerInput(session = session, inputId = "p2",
choices = middle_class)
}
if(input$p1 %in% c("Option3")){
updatePickerInput(session = session, inputId = "p2",
choices = list(major = major_class,
middle = middle_class))
}
if(input$p1 %in% c("Option4")){
updatePickerInput(session = session, inputId = "p2",
choices = major_class)
}
})
observeEvent(input$p3 ,{
if(input$p1 %in% c("Option1")){
output$resule_message <- renderText({
paste0("expression1")
})
}
else{
output$resule_message <- renderText({
paste0("expression2")
})
}
})
}
shinyApp(ui = ui, server = server)
Those who can solve this problem, those who know how to change the processing flow depending on the input conditions of PikcerInput,
If you know that you can do something similar using another method, please let me know.
One way to do it is to use renderUI for your second pickerInput and display it based on your conditions. Try this
library("shiny")
library("shinyWidgets")
major_class <- c("A1","A2","A3")
middle_class <- c("A1_1","A1_2","A2_1","A2_2","A3_1","A3_2")
ui <- fluidPage(
fluidRow(
column(
width = 2, offset = 1,
pickerInput(
inputId = "p1",
label = "PickerInput1",
choices = c("Option1","Option2","Option3","Option4"),
options = list(
`live-Search` = TRUE,
`actions-box` = TRUE,
size = 7,
`selected-text-format` = "count > 3"
),
multiple =FALSE
)
),
column(
width = 2, uiOutput("pickr2"), uiOutput("numinput")
),
column(
width = 2,
actionButton("p3","finish")
),
textOutput("resule_message")
)
)
server <- function(input, output, session) {
output$pickr2 <- renderUI({
req(input$p1)
if(input$p1 %in% c("Option1","Option2")){
choices <- middle_class
TORF <- FALSE
}else{
TORF <- TRUE
if(input$p1 %in% c("Option3")){
choices <- c(middle_class,major_class)
}else choices <- major_class
}
pickerInput(
inputId = "p2",
label = "PickerInput2",
choices = choices,
options = list(
`live-Search` = TRUE,
`actions-box` = TRUE,
size = 7,
`selected-text-format` = "count > 3"
),
multiple =TORF
)
})
output$numinput <- renderUI({
req(input$p1)
if(input$p1 %in% c("Option2")){
numericInput("num", label = "Numeric input", value = 1)
}else return(NULL)
})
observeEvent(input$p3 ,{
req(input$p1)
if(input$p1 %in% c("Option1")){
output$resule_message <- renderText({
paste0("expression1")
})
}else{
output$resule_message <- renderText({
paste0("expression2")
})
}
})
}
shinyApp(ui = ui, server = server)
I would like that when user exits the selectizeInput field (clicks outside of selectizeInput), a new option is created and selected (option createOnBlur = TRUE), but I can't figure out how to control the created values to ensure they belong to the "choices" list.
In fact, I would like createOnBlur=TRUE working with create=FALSE, but this obviously doesn't work..
I have looked at selectize.js documentation and I think createFilter and/or onBlur() options could be useful but I didn't succeed in implementing it for my purpose.
Here is a reprex with an age input, I would like that when user tape e.g. "40" and then clik outside of input without pressing "Enter" (ie onBlur), the value 40 is recorded in the input, but if the user tape e.g "444", this impossible age value is not created in the list of choices :
library(shiny)
input_age <- function(mina = 0, maxa =100){
selectizeInput(inputId = "age",
label = "Age",
choices = c("choose one" = "", mina:maxa),
options = list(create = TRUE,
createOnBlur = TRUE)
)
}
ui <- shinyUI(fluidPage(
titlePanel("selectize createonblur"),
mainPanel(
input_age(mina = 20, maxa = 70)
)
))
# SERVER
server <- shinyServer(function(input, output) {
})
shinyApp(ui, server)
You can use updateSelectizeInput to check the selection made against the choices after each interaction with your input.
Please see the following:
library(shiny)
input_age <- function(mina = 0, maxa = 100){
selectizeInput(inputId = "age",
label = "Age",
choices = c("choose one" = "", mina:maxa),
options = list(create = TRUE,
createOnBlur = TRUE)
)
}
minAge <- 20
maxAge <- 70
ui <- shinyUI(fluidPage(
titlePanel("selectize createonblur"),
mainPanel(
input_age(mina = minAge, maxa = maxAge)
)
))
# SERVER
server <- shinyServer(function(input, output, session) {
observeEvent(req(input$age), {
if(length(setdiff(input$age, as.character(seq(minAge, maxAge)))) > 0){
updateSelectizeInput(session,
inputId = "age",
choices = seq(minAge, maxAge),
selected = "")
}
})
})
shinyApp(ui, server)
Update - Here is a JS approach:
library(shiny)
input_age <- function(mina = 0, maxa = 100){
selectizeInput(inputId = "age",
label = "Age",
choices = c("choose one" = "", mina:maxa),
options = list(create = TRUE,
createOnBlur = TRUE))
}
ui <- shinyUI(fluidPage(
tags$head(tags$script(HTML("
$(document).on('shiny:inputchanged', function(event) {
if (event.name === 'age') {
if (isNaN(parseInt(event.value)) || event.value > 70 || event.value < 20) {
var $select = $('#age').selectize();
var selectize = $select[0].selectize;
selectize.setValue(null, true);
}
}
});
"))),
titlePanel("selectize createonblur"),
mainPanel(
input_age(mina = 20, maxa = 70)
)
))
# SERVER
server <- shinyServer(function(input, output, session) {
})
shinyApp(ui, server)
You can supply a regular expression to the createFilter option. If the user types something which doesn't match this regular expression, then "Add ..." will not appear and it will not be possible to add this item.
library(shiny)
ui <- fluidPage(
titlePanel("selectize createonblur"),
mainPanel(
selectizeInput(
inputId = "age",
label = "Age",
choices = c("choose one" = "", 20:70),
options = list(
create = TRUE,
createOnBlur = TRUE,
createFilter = I("/^([2-6][0-9]|70)$/")
)
)
)
)
server <- function(input, output, session) {}
shinyApp(ui, server)
UpdateSliderInput not working...
Hi All,
Seems like a challenge updating sliderInput. So i wanted to develop an application in a way so that filter can be applied dynamically wherein one of the variables needs to be provided with a slider.
Any help can be really appriciable.
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fluidRow(
column(6, actionButton('addFilter', 'Add filter')),
offset = 6
),
tags$hr(),
tags$div(id = 'placeholderAddRemFilt'),
tags$div(id = 'placeholderFilter'),
tags$div(id = 'placeholderFilter')
# width = 4 # sidebar
),
mainPanel(
tableOutput("data")
)
)
)
server <- function(input, output,session) {
filter <- character(0)
makeReactiveBinding("aggregFilterObserver")
aggregFilterObserver <- list()
observeEvent(input$addFilter, {
add <- input$addFilter
filterId <- paste0('Filter_', add)
colfilterId <- paste0('Col_Filter_', add)
rowfilterId <- paste0('Row_Filter_', add)
removeFilterId <- paste0('Remove_Filter_', add)
headers <- names(mtcars)
insertUI(
selector = '#placeholderFilter',
# ui = tags$div(id = filterId,
# actionButton(removeFilterId, label = "Remove filter", style = "float: right;"),
# selectInput(colfilterId, label = "Some Filter", choices = as.list(headers), selected = 1),
# sliderInput(rowfilterId, label = "Select variable values",
# min = 1, max = 2, value = 1:4)
# )
ui = tags$div(column(9,id = filterId,
actionButton(removeFilterId, label = "Remove filter", style = "float: right;"),
selectInput(colfilterId, label = "Some Filter", choices = headers, selected = NULL),
conditionalPanel(condition = paste0("input.",colfilterId," != 'mpg'"),
checkboxGroupInput(rowfilterId, label = "Select variable values",
choices = NULL, selected = NULL, width = 4000)),
conditionalPanel(condition = paste0("input.",colfilterId," == 'mpg'"),
sliderInput(rowfilterId,
label = 'select values',
min = 1,#min(datafile$Age),
max = 10,#max(datafile$Age),
value = 1:5))#c(min(datafile$Age),max(datafile$Age))))
)
)
)
observeEvent(input[[colfilterId]], {
col <- input[[colfilterId]]
values <- as.list(unique(mtcars[col]))[[1]]
print(values)
print(paste0("example",as.list(unique(mtcars[col]))))
#
# updateCheckboxGroupInput(session, rowfilterId , label = "Select variable values",
# choices = values, selected = values, inline = TRUE)
#
updateSliderInput(session, rowfilterId , min = min(values), max = max(values), value = c(min(values),max(values)))
updateCheckboxGroupInput(session, rowfilterId , label = "Select variable values",
choices = values, selected = values, inline = TRUE)
aggregFilterObserver[[filterId]]$col <<- col
aggregFilterObserver[[filterId]]$rows <<- NULL
})
observeEvent(input[[rowfilterId]], {
rows <- input[[rowfilterId]]
aggregFilterObserver[[filterId]]$rows <<- rows
})
observeEvent(input[[removeFilterId]], {
removeUI(selector = paste0('#', filterId))
aggregFilterObserver[[filterId]] <<- NULL
})
})
output$data <- renderTable({
dataSet <- mtcars
invisible(lapply(aggregFilterObserver, function(filter){
dataSet <<- dataSet[which((dataSet[[filter$col]] %in% filter$rows)), ]
}))
dataSet
})
}
shinyApp(ui = ui, server = server)
Mpg values are not being updated, Is this due to conditionalPanel because of which the sliderInput is not being updated?
Everything seems to be perfect apart from the inputid you are using for 2 input types.
I just created one more variable for Sliderinput which will create dynamic input id.
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fluidRow(
column(6, actionButton('addFilter', 'Add filter')),
offset = 6
),
tags$hr(),
tags$div(id = 'placeholderAddRemFilt'),
tags$div(id = 'placeholderFilter'),
width = 4 # sidebar
),
mainPanel(
tableOutput("data")
)
)
)
server <- function(input, output,session) {
filter <- character(0)
makeReactiveBinding("aggregFilterObserver")
aggregFilterObserver <- list()
observeEvent(input$addFilter, {
add <- input$addFilter
filterId <- paste0('Filter_', add)
colfilterId <- paste0('Col_Filter_', add)
rowfilterId <- paste0('Row_Filter_', add)
rowfilterId_num <- paste0('Row_Filter_num_', add)
removeFilterId <- paste0('Remove_Filter_', add)
headers <- names(mtcars)
insertUI(
selector = '#placeholderFilter',
ui = tags$div(id = filterId,
actionButton(removeFilterId, label = "Remove filter", style = "float: right;"),
selectInput(colfilterId, label = "Some Filter", choices = as.list(headers), selected = 1),
sliderInput(rowfilterId_num, label = "Select variable values",
min = 1, max = 2, value = 1:4)
)
)
observeEvent(input[[colfilterId]], {
print(rowfilterId)
print(paste0(input[[colfilterId]]))
col <- input[[colfilterId]]
values <- as.list(unique(mtcars[col]))[[1]]
print(values)
print(paste0("example",as.list(unique(mtcars[col]))))
updateCheckboxGroupInput(session, rowfilterId , label = "Select variable values",
choices = values, selected = values, inline = TRUE)
updateSliderInput(session, rowfilterId_num , label = "Select variable",min = min(values), max = max(values), value = c(min(values),max(values)))
aggregFilterObserver[[filterId]]$col <<- col
aggregFilterObserver[[filterId]]$rows <<- NULL
})
observeEvent(input[[rowfilterId]], {
rows <- input[[rowfilterId]]
aggregFilterObserver[[filterId]]$rows <<- rows
})
observeEvent(input[[removeFilterId]], {
removeUI(selector = paste0('#', filterId))
aggregFilterObserver[[filterId]] <<- NULL
})
})
output$data <- renderTable({
dataSet <- mtcars
invisible(lapply(aggregFilterObserver, function(filter){
dataSet <<- dataSet[which((dataSet[[filter$col]] %in% filter$rows)), ]
}))
dataSet
})
}
shinyApp(ui = ui, server = server)
just check and let me know that this is what you wanted to achieve. let me know incase any thing else is required.
here is part of code I have written, and the problem I am having is that after selecting both player 1 and player, if I wish to change player 1 again, player 2 also resets. I had to make Player 2's input dependent on Player1 because I do not want the user to be able to select the same player for both the dropdowns. Here is my code:
server.R
shinyServer <- function(input, output) {
# Creates the first drop down menu through which the user can select the first player.
output$firstdropdown <- renderUI({
selectizeInput("player1", label = "Choose Player 1:", choices = winrateRole(input$role)$player,
selected = NULL, multiple = FALSE, options = NULL)
})
# Creates the second drop down menu. User cannot select the same player he/she select as the first player.
output$seconddropdown <- renderUI({
all.choices <- winrateRole(input$role)$player
without.player1 <- all.choices[which(all.choices != input$player1)]
selectizeInput("player2", label = "Choose Player 2:", choices = without.player1,
selected = NULL, multiple = FALSE, options = NULL)
})
ui.R
shinyUI <- fluidPage(
navbarPage(strong("Test1"),
tabPanel("Overview"),
tabPanel("Tab1",
sidebarLayout(
sidebarPanel(
uiOutput("firstdropdown"),
br(),
uiOutput("seconddropdown")
)
))
)
winrateRole
winrateRole <- function(role) {
blue.role <- paste0("blue", role)
blue <- league.data %>%
group_by_(blue.role) %>%
summarise(winrate.blue = round((sum(bResult) / n() * 100), digits = 2)) %>%
arrange_(blue.role) %>%
select(player = blue.role, winrate.blue)
red.role <- paste0("red", role)
red <- league.data %>%
group_by_(red.role) %>%
summarise(winrate.red = round((sum(rResult) / n() * 100), digits = 2)) %>%
arrange_(red.role) %>%
select(player = red.role, winrate.red)
return (left_join(blue, red))
}
your problem is that you recreate the whole input everytime the value of the first select changes.
In this case you want to use the updateInput method which only changes the values you want but leaves the rest unchanged. Unfortunatly updateSelectizeInput seems to reset selected every time choises are changed so you need to save the value of the input in a reactivevariable.
server <- function(input, output, session) {
current_selection <- reactiveVal(NULL)
observeEvent(input$player2, {
current_selection(input$player2)
})
# update player 2
observeEvent({
input$player1
},{
all.choices <- winrateRole
without.player1 <- all.choices[which(all.choices != input$player1)]
updateSelectInput(
inputId = "player2",
session = session,
selected = current_selection(),
choices = without.player1
)
},
ignoreInit = FALSE
)
output$firstdropdown <- renderUI({
selectizeInput(
"player1",
label =
"Choose Player 1:",
choices = winrateRole,
selected = NULL,
multiple = FALSE,
options = NULL) })
# Creates the second drop down menu. User cannot select the same player he/she select as the first player.
output$seconddropdown <- renderUI({
selectizeInput(
"player2",
label = "Choose Player 2:",
choices = winrateRole,
selected = NULL,
multiple = FALSE,
options = NULL)})
}
** ui.R**
shinyUI <- fluidPage(
navbarPage(strong("Test1"),
tabPanel("Overview"),
tabPanel("Tab1",
sidebarLayout(
sidebarPanel(
uiOutput("firstdropdown"),
br(),
uiOutput("seconddropdown")
))
)