shinyWidgets icon indicating copy to clipboard operation
shinyWidgets copied to clipboard

[Feature Request] A numeric input/range slider/numeric input combo.

Open alawy23 opened this issue 5 years ago • 5 comments

Hello. I am new to R and to Shiny, and this is my first GitHub issue submission (ever). I searched around for a solution for my issue, but couldn't find an easy one. I managed to make a workaround for it, but it did not satisfy me. So, I thought I would see if there is a solution for this, or if someone is willing to make this new widget.

Issue:

I am trying to make a range slider to filter my data. This widget will be placed in a dropdown menu (dropdown()) to make my main panel focused on a plot. My data for this slider ranges from 0-50000. This made it difficult to get an accurate filter (especially in such a small space ). See the following gif: slider_issue (See that this filter jumps an increment of 100 <yes, I have specified a step of 1>)

Workaround:

To solve this problem I made a numericInput/sliderInput/numericInput combo (inspired by Tableau). This way the user can specify their values in writing. slider_workaround

Workaround Problems:

The combo is aesthetically awkward. It also needs a lot of trial and error to make it fit a specific page (or a dropdown menu in my case). It requires a lot of code lines, making the script awkward too. See the reprex code below.

Suggested Solution:

A new widget that natively combines the three elements (or two if the user did not wish for a range slider). For example:

sliderInputCombo(
  inputId,
  label,
  min,
  max,
  # if value is a character vector of two, you get a range slider, and another input box.
  value,
  step=NULL,
  # a position argument for the placement location of the input box (top, bottom, sides).
  boxPosition = "top"
  # and so on
)

Workaround Code: (I tried my best to make it a reprex )

library(shiny)
library(shinyWidgets)

shinyApp(
  ui = fluidPage(
    # I am using the dropdown menu to showcase the issue of small space with
    # numericInput/sliderInput/numericInput combo.
    dropdown(
      width = "700px",
      fluidRow(
        column(
          3,
          # This is to remove whitespace between the columns, making the combo look neater.
          # (from  Xiongbing Jin from stackoverflow)
          style = 'padding:0px;',
          # This is to make the font smaller in the numeric input box.
          # (from Geovany from stackoverflow)
          tags$style("#obs_min {font-size:10px;height:10px;}"),
          numericInput(
            "obs_min",
            NULL,
            min = 0,
            max = 50000,
            value = 0
          )
        ),
        column(6, HTML("<center>Observation</center>")),
        column(
          3,
          style = 'padding:0px;',
          tags$style("#obs_max {font-size:10px;height:10px;}"),
          numericInput(
            "obs_max",
            NULL,
            min = 0,
            max = 50000,
            value = 50000
          )
        )
      ),
      fluidRow(column(
        12,
        style = 'padding:0px;',
        sliderInput(
          'obs',
          label = NULL,
          min = 0,
          max = 50000,
          value = c(0, 50000),
          step = 1,
          width = 'auto'
        )
      ))
    )),
  
  server = function(input, output, session) {
    # I had to use four observeEvents to make this one combo.
    observeEvent(input$obs, {
      updateNumericInput(session, "obs_min", value = input$obs[1])
    })
    observeEvent(input$obs, {
      updateNumericInput(session, "obs_max", value = input$obs[2])
    })
    observeEvent(input$obs_max, {
      updateSliderInput(session, "obs",
                        value = c(input$obs[1], input$obs_max))
    })
    observeEvent(input$obs_min, {
      updateSliderInput(session, "obs",
                        value = c(input$obs_min, input$obs[2]))
    })
  }
  
)

alawy23 avatar Feb 17 '20 01:02 alawy23

Hello @alawy23 , welcome to R and Shiny 🎉 Very good first issue 👍

Interesting problem, never been confronted to this case, don't know if I can come up with someting better than your solution.

It will make a good shiny module, or maybe the synchronization can be done in JavaScript to avoid the server part 🤔

I don't have a lot of time for this, but I'm keeping that in mind. If you want to make a PR with a module with those functionnalities, I'll review it.

Victor

pvictor avatar Feb 25 '20 08:02 pvictor

Hello all, I stumbled upon this while looking at something else, but just my two cents; I did something similar in a completely different environment, but the idea might serve you well.

I had a slider which posed the same problem, I assigned SHIFT a different meaning, the slider would move freely by default and move by 100's (or whatever) if the user kept pressing shift while moving the slider.

bwh avatar Feb 29 '20 17:02 bwh

@alawy23 this is an interesting idea. I am the contributor of the numericRangeInput widget and I created it for just this scenario. I develop daily in both Shiny and Tableau, and I got the idea for numericRangeInput() from Tableau's slider option that also shows the input boxes. What I found in discussing with my users is that, while the slider can be aesthetically pleasing, it is often very difficult to use due to the lack of precision in moving the slider, especially when dealing with large ranges. In the case of my users they found that having just the input boxes (via numericRangeInput()) was much easier to use than the slider.

wkdavis avatar Mar 04 '20 17:03 wkdavis

I want to upvote the issue raised by @alawy23. I love the slider because it very naturally enforces the range the numbers can accept, but many of my users need more fine grained input controls. My use case is not a range but a single numeric input, although I imagine one would easily extend to the other. I have found quite a few people who have been asking for this on SO and other places, but the only answers I've ever seen are workarounds, not built-in solutions. Avoiding server side processing to get the box and slider in sync would be important, IMO.

If there is an openness to a pull request, I might try to put something together, but I'm fairly new to CRAN development and would love to understand what your expectations are for pull requests.

jntrcs avatar Aug 20 '20 16:08 jntrcs

Hi all, this would be really a great feature! Hope it will be included in the future :)

AndreasUntch avatar Jul 16 '21 11:07 AndreasUntch