updateSelectizeInput observer only accepts my selection for an instant before resetting

I am building a Shiny app that allows users to build a roster for home-ran Fantasy Football league during the playoff season. Users can only pick one player from each team that makes it to the playoffs. Therefore, I want to update my selectizeInput choices to remove players if their team has been selected due to a prior selection. I've created several textOutput helpers to test that my filtering logic works, and on that side I am mostly confident that it is working. But when I add an observe() with updateSelectizeInput() the input does not work the way I expect. When I select, I can see the new value for a fraction of a second and then the value gets overwritten to an empty or NULL value (as if I never made a selection).

I've paired down my app to a relatively small minimally reproducible example that exhibits the same behavior as the full app (although I could provide the full code if preferred). You'll see the updateSelectizeInput(...) at the very bottom of this code chunk.

I'm sure it is something that I'm doing but for the life of me I can't figure it out. Appreciate any help/insight you can provide!

library(tidyverse)
library(shiny)
library(data.table)

players <- data.table(
  team = c("ARI","LAC","PHI", "LAC", "PHI"),
  player = c("Player 1", "Player 2", "Player 3", "Player 4", "Player 5")
)

ui <- fluidPage(
  titlePanel("Playoff Fantasy Football"),
  tabsetPanel(
    tabPanel(
      "Regular Season 2023 Stats"
    ),
    tabPanel(
      "Select Roster",
      sidebarLayout(
        sidebarPanel(
          selectizeInput(
            inputId = "roster_selections_made",
            label = "Select Players and Defensive Team:",
            choices = c("",players$player),
            options = list(maxItems = 14)
          ),
          width = 3
        ),
        mainPanel(
          textOutput("teams_remaining_text"),
          textOutput("players_remaining_text")
        )
      )
    )
  )
)

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

  teams_selected <- reactive({
    players[player %in% input$roster_selections_made, team] %>%
      unique() %>%
      sort()
  })
  
  teams_remaining <- reactive({
    players[!(team %in% teams_selected()), team] %>%
      unique() %>%
      sort()
  })

  output$teams_remaining_text <- renderText({
    paste0("Teams remaining: ", paste0(teams_remaining(), collapse = ", "))
  })

  players_remaining <- reactive({
    players %>%
      filter(team %in% teams_remaining()) %>%
      distinct(player) %>%
      arrange(player)
  })

  output$players_remaining_text <- renderText({
    paste0("Players remaining: ", paste0(players_remaining()$player, collapse = ", "))
  })


  # if you comment out the observe() below, the app generally works as expected
  observe({
    updateSelectizeInput(
      session,
      inputId = "roster_selections_made",
      choices = players_remaining()$player
    )
  })

}


shinyApp(ui, server)

Please check the following info on circular references in shiny:

1 Like

I haven't run the code, but I percieve a cycle.

selectize roster_selections_made depends on players_remaining() which depends on teams_remaining() which depends on teams_selected() which depends on selectize roster_selections_made which depends on ...

1 Like

Thanks! Rereading this section now!

Thanks! Reading the section on circular references now, so hopefully I have this fixed shortly!

@nirgrahamuk @ismirsehregal

Thanks for the guidance. I was able to resolve my issue by using observeEvent() tied to an actionButton() as opposed to an observe() with no actionButton. I explored around and was hoping that I could find an option = list() within selectizeInput where I could change the event type (such as onClick) so that it could work without the actionButton() but I didn't find anything. Anyway, things are working and I learned a bunch!

Thanks for your help!

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.