I have spend more than 2 hours to find a solution. By the way I have learned two things :
- when a reactive object is recalculated but the result is the same as the previous one, then its receptors are not updated (please correct me if I'm wrong), very good to know that
- with updateSliderInput(), we can only update the current value of the slider, not the min and the max
My first idea was to use updateSliderInput() rather than renderUI({}) to update the slider, but as I said before, it does not allow to update the range of the slider. Finally I have found the following solution (code below). The idea is :
1) isolate mainData() to avoid double calculation ; thus the table output is only reactive to the slider value
2) construct a reactive indicator which is updated each time the data has changed but the slider value has not changed (and which is not updated in other cases)
3) connect the table output to this reactive indicator
I would be glad to know whether someone has an easier solution ! (I would also be glad to hear some comments about this difficulty with renderUI({}))
library(shiny)
runApp(
list(
server=function(input, output, session) {
globalData <- data.frame("vec1" = c(1,2,3), "vec2" = c(1,1,5) , "vec3" = c(2,5,6))
mainData <- reactive({
data <- do.call("$",list(globalData,input$vector))
return(data)
})
value_has_not_changed <- reactiveValues(x=0)
output$slider_rangeInput <- renderUI({
data <- mainData()
newvalue <- data[1]
slider <- isolate(input$slider)
if(!is.null(slider)){
if(newvalue == slider) value_has_not_changed[["x"]] <- isolate(value_has_not_changed[["x"]]) + 1
}
sliderInput(inputId="slider",label = "Range", min=data[1],max = data[3], value = newvalue)
})
output$contents <- renderTable({
return(globalData)
})
output$result <- renderTable({
if(is.null(input$slider)){
return(NULL)
}
w <- value_has_not_changed[["x"]] # makes the reactive connection to value_has_not_changed[["x"]]
# data <- mainData() * slider
data <- isolate(mainData()) * input$slider
print(data)
return(data.frame(data))
})
},
ui=pageWithSidebar(
headerPanel("Test"),
sidebarPanel(
selectInput(inputId = "vector",
label = "Values vector",
choices = list("vec1","vec2","vec3"))
),
mainPanel(
htmlOutput("slider_rangeInput"),
tableOutput('contents'),
tableOutput('result')
)
)))