10

I am currently working on a dashboard with multiple sliderInputs. Is it possible to replace the max and min labels with text? For example, my min = 1 and max = 10. I want to keep the scale from 1 to 10 while having the slider labels appear as "sooner" and "later" respectively.

Thanks!

Caleb Lam
  • 111
  • 1
  • 6

4 Answers4

8

The short answer here is no, sadly; short of hacking through the underlying code in JavaScript, there is no way to relabel slider ticks (though there are a few formatting parameters).

However, you can hack the labels into the widget label by passing it an HTML object styled with inline CSS. Make sure to set the width of the widget itself so everything lines up, and the result is not too bad:

library(shiny)

ui <- fluidPage(

    sliderInput(inputId = 'slider', 
                label = div(style='width:300px;', 
                            div(style='float:left;', 'sooner'), 
                            div(style='float:right;', 'later')), 
                min = 0, max = 10, value = 5, width = '300px')

    )

server <- function(input, output) {

}

shinyApp(ui, server)

labeled slider

alistaire
  • 42,459
  • 4
  • 77
  • 117
5

this can be done by manipulating the prettify function of ionRangeSlider, which returns the slider labels for each value in the range of selectable slider values. Simply create a file slider.js as following (enter your slider ID and lowest selectable value at marked spots) and include it in your app with includeScript('slider.js'):

$(document).ready(function() {
  /**
    Custom slider labels
  **/

    // Convert numbers of min to max to "lower" and "higher"
    function returnLabels(value) {
      // remove label of selected
      $('.my_slider').find('.irs-single').remove();
    //  $('.my_slider').find('.irs-grid-text').remove(); // this is an alternative to ticks=F

      if (value === 0){ // enter your lowest slider value here
        return "lower";
      }else{
        return "higher";
      }
    }

    var someID = $("#YOUR_SLIDER_ID").ionRangeSlider({ // enter your shiny slider ID here
          prettify: returnLabels,
          force_edges: true,
          grid: false
        });
    });

Then, wrap your slider in a div with class "my_slider":

library(shiny)    
ui <- fluidPage(
  includeScript("slider.js"),
  div(class="my_slider", # to be able to manipulate it with JQuery
      sliderInput("YOUR_SLIDER_ID",
                  "Slider Value:", ticks = F,
                  min = 0, max = 50, value = 30))      
)

server <- function(input, output) {}    
shinyApp(ui, server)

The result looks as follows:

enter image description here

To fix the bug that labels disappear when min/max value is selected, define this UIoutput in your app:

# Just a small fix to reactivate Labels when Min/Max value is chosen
output$fixSlider <- renderUI({     
 # declare dependency on slider
 input$YOUR_SLIDER_ID     
 minVis <- "$('.my_slider').find('.irs-min').attr('style','visibility: visible');"
 maxVis <- "$('.my_slider').find('.irs-max').attr('style','visibility: visible');"  
 return(tags$script(paste(minVis,maxVis)))
})

You're welcome :-)

shosaco
  • 5,915
  • 1
  • 30
  • 48
  • Your approach looks promising, but I cannot get it working. Could you provide an example to copy&paste including the R-code? Beside: I think you mean includeScript('labels.js') – Julian Aug 07 '18 at 10:24
  • Thanks Julian. I did add the minimal shiny app code. Noticed I used # for Javascript comments, which was wrong ( // is correct). See if that fixes your problem. – shosaco Aug 07 '18 at 14:10
  • now it works for me. It is important that the call to includeScript("slider.js") is made inside the call to the Shinypage (fluidpage). And the "#" in front of "YOUR_SLIDER_ID" is also important ;-) – Julian Aug 07 '18 at 15:02
  • Additionally: You can leave the label of the selected (comment out the line), if you repleace the if-clause with: `if (value === 1){ /** enter your lowest slider value here **/ return "lower"; }else if (value === 50){/** enter your highest slider value here **/ return "higher"; } else return value;` – Julian Aug 07 '18 at 15:05
1

Maybe somethin like this. Just note that the slider will return an index starting from zero.

app.R

    library(shiny)

    df <- data.frame(x=1:24)


    ui <- tagList(
            tags$head(
                    HTML("<script type='text/javascript' src='js/sliderInit.js'></script>")
            ),
            fluidPage(


       titlePanel("Custom firs and last label"),


       sidebarLayout(
          sidebarPanel(
             sliderInput("hour",
                         "Select hour:",
                         min = 1,
                         max = 10,
                         value = 5)
          ),


          mainPanel(
             textOutput("selectedNumber")
          )
       )
    ))


    server <- function(input, output) {

       output$selectedNumber <- renderText({
               df[input$hour+1,]
       })
    }


    shinyApp(ui = ui, server = server)

sliderInit.js

$(document).ready(function() {
    $("#hour").ionRangeSlider({
            values: ["Sooner", "2", "3", "4", "5", "6", "7", "8", "9", "Later"]
    });
    });
Valter Beaković
  • 3,140
  • 2
  • 20
  • 30
0

I had the same problem with you. Unfortunately, neither Shiny nor ionRangeSlider provides an easy functionality for such changes. After looking for a subtler way with sheer stubbornness, I came across the following CSS hack. (I also hid the value cursor with JS.)

ui <- fluidPage(

tags$head(
    #Using ionRangeSlider's javascript options you can hide/show selector labels and min/max labels
    HTML("
    <script>
    $(document).ready(function(){
        $(\".js-range-slider\").ionRangeSlider({
        hide_min_max: false,
        hide_from_to: true
        });

    });

    </script>
    ")
),

#This CSS hack first hides the text within the span tags of the specified classes
#Then it adds desired text and CSS properties. !important parameter is to override
#inline css parameters.
tags$style(type = "text/css", "
    .irs-min {visibility:hidden !important;}
    .irs-max {visibility:hidden !important;}
    .js-irs-0 .irs .irs-min:after {content:'Hello' !important;}
    .js-irs-0 .irs .irs-max:after {content:'Shiny' !important;}
    //Restore css defaults to .irs-min and .irs-max
    .irs-min:after {
        visibility: visible !important;
        display: block;
        background: rgba(0, 0, 0, 0.1) none repeat scroll 0 0;
        border-radius: 3px;
        color: #333;
        font-size: 10px;
        line-height: 1.333;
        padding: 1px 3px;
        text-shadow: none;
        top: 0;
        cursor: default;
        display: block;
        left: 0;
        position: absolute;}

    .irs-max:after {
        visibility: visible !important;
        display: block;
        background: rgba(0, 0, 0, 0.1) none repeat scroll 0 0;
        border-radius: 3px;
        color: #333;
        font-size: 10px;
        line-height: 1.333;
        padding: 1px 3px;
        text-shadow: none;
        top: 0;
        cursor: default;
        display: block;
        right: 0;
        position: absolute;}

"),

sliderInput(inputId="test", label=NULL, min=1, max=10, value=5, step = 1, width='100%')

)

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

   }

shinyApp(ui = ui, server=server)
berkorbay
  • 443
  • 7
  • 22