1
votes

I have a shiny app where I have 2 filter choices ("an option" and "another option"). The timeline starts with "an option" selected. If the user selects an item in the timeline, some text appears. What I would like to do is set the input$timeline_selected value back to NULL if the user has selected something in the timeline, but then chooses a different filter choice before clearing the selection. For example, in this simple app, if the user has the filter set to "an option", then selects "item one" on the timeline, then changes the filter to "another option" before clearing the selection, the "selection id" is still 1 even though that item isn't shown on the timeline when the filter is changed.

What I would like to have happen is the following: user has filter set to "an option", then selects "item one" on the timeline, then changes the filter to "another option" (before clearing the selection), then the input$timeline_selected value gets reset to NULL.

library(shiny)
library(dplyr)

dataBasic <- data.frame(
  id = 1:4,
  content = c("Item one", "Item two" ,"Ranged item", "Item four"),
  start   = c("2016-01-10", "2016-01-11", "2016-01-20", "2016-02-14"),
  end    = c(NA, NA, "2016-02-04", NA), 
  selection = c("an option", "an option", "another option", "another option")
)


ui <- fluidPage(
  sidebarPanel(radioButtons(inputId = "filter",
               label = "Select filter:",
               choices = unique(dataBasic$selection),
               selected = "an option")
  ),
  mainPanel(wellPanel(timevisOutput("timeline")
                      ), 
            wellPanel(htmlOutput(outputId = "text"),
                      textOutput("selected", inline = TRUE)
                      )
            )
)

server <- function(input, output){
  # Create timeline
  output$timeline <- renderTimevis({
    req(input$filter)
    dataBasic %>% 
      filter(selection == input$filter) %>% 
      timevis()
  })


  output$text <- renderText({

    if (!is.null(input$timeline_selected)) {
      input$timeline_data %>% 
        filter(id == input$timeline_selected) %>% 
        pull(content)
    }
  })

  output$selected <- renderText(
    paste("selection id: ", input$timeline_selected)
  )

  # clear selection if different filter is chosen
  # observeEvent(input$filter, {
  #    input$timeline_selected <- NULL
  #  })

}
shinyApp(ui = ui, server = server)

I tried using

observeEvent(input$filter, {
      input$timeline_selected <- NULL
    })

but then I get an error stating "Attempted to assign value to a read-only reactivevalues object"

I thought about using setSelection but in the help for timevis under the input$mytime_selected it states "Note that this will not get updated if an item is selected programmatically using setSelection."

My app is more involved than this example and I am filtering data based on the id and it is showing errors when I change the filter from one option to another, so being able to reset the input$timeline_selected value back to NULL will solve my problem.

Thanks in advance for your help!

1

1 Answers

2
votes

You could simply introduce a reactiveValue as an intermediary variable that:

  1. Takes the value of input$timeline_selected whenever it is changed
  2. Set to NULL when the value of input$filter changes

Add the following code to your server function:

# Define reactiveValue
rv <- reactiveValues(selected = NULL)

# 1. Pass value of input$timeline_selected to Reactive Value
observe( {
  rv$selected <- input$timeline_selected
})

# 2. clear selection if different filter is chosen
observeEvent(input$filter, {
  rv$selected <- NULL
})

Then change input$timeline_selected in the code to the reactive value:

output$text <- renderText({
  if (!is.null(rv$selected)) {
    input$timeline_data %>% 
      filter(id == rv$selected) %>% 
      pull(content)
  }
})

output$selected <- renderText(
  paste("selection id: ", rv$selected)
)

Please note that there could be a more trivial solution in the package that I am not familiar with.