Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R shiny bi-directional reactive widgets

Tags:

r

shiny

I am struggling to figure out how to get 2 R Shiny widgets to update each other. For example, a slider widget that can update a text box widget, and visa versa, where the end user can choose to use either widget.

This question is similar, but has no answer, so I am giving what is (hopefully) a simpler example. Retrieving reactive dependencies as inferred by shiny::reactive(). If this question is answered elsewhere, I have been unable to find such an answer.

I would like to know if I can move slider1 to move slider2 and slider2 to move slider1. Right now I only can do the first part (I can move slider1 to move slider2). If I can do this, I am thinking I could make widget 1 a slider, and widget 2 a numerical input, with much the same code.

The below example was modified from http://shiny.rstudio.com/gallery/update-input-demo.html and it is as minimal an example as I could make. It was also the only app I could find that came close to what I was looking for, although I realize a very different approach may needed...

Server.R Code

shinyServer(
  function(input, output, clientData, session) {

#### one way interaction between slider 1 and 2 ####
    observe({![enter image description here][1]   
      c_label <- input$control_label
      c_num <- input$control_num  # <- input$inSlider

      # Slider input =============================================
      updateSliderInput(session, "inSlider",
                        label = paste("Slider2", c_label),
                        value = c_num)
      updateSliderInput(session, "control_num",
                        label = paste("Slider1", c_label),
                        value = c_num)
    })
})

Ui.r Code

shinyUI(fluidPage(
  titlePanel("One Way Reactive Slider"),
  fluidRow(
    column(3,
           wellPanel(
             h4("Slider Inputs"),
             sliderInput("control_num",
                         "This controls values:",
                          min = 1, max = 20, value = 15),
             sliderInput("inSlider", "Slider input:",
                          min = 1, max = 20, value = 15)
    ))

  )
))

Below is a picture of the app while running. Moving slider 1 moves slider 2, but the opposite is not true (which is what I would like to do).

like image 331
greenbooks Avatar asked Jan 07 '15 20:01

greenbooks


1 Answers

The trick is to create a dynamic UI. In this way, you can update a slider-drawing expression on changes in the other UI elements and rebuild a slider widget using a different default value:

server.R

shinyServer(
    function(input, output, clientData, session) {

    output$slider1 <- renderUI({
       slider2.value <- input$inSlider
       default.slider1 <- if (is.null(slider2.value)) 15 else slider2.value
       sliderInput("control_num",
                   "This controls values:",
                    min = 1, max = 20, value = default.slider1)
    })

    output$slider2 <- renderUI({
       slider1.value <- input$control_num
       default.slider2 <- if (is.null(slider1.value)) 15 else slider1.value
       sliderInput("inSlider", "Slider input:",
                    min = 1, max = 20, value = default.slider2)
    })

  })

ui.R

    shinyUI(fluidPage(
      titlePanel("One Way Reactive Slider"),
      fluidRow(
        column(3,
               wellPanel(
                 h4("Slider Inputs"),
                 uiOutput('slider1'),
                 uiOutput('slider2')
        ))

      )
    ))
like image 66
Marat Talipov Avatar answered Oct 04 '22 05:10

Marat Talipov