I am using a simple slider bar in a shiny app to define a value range. I have noticed that you can quite usefully slide the range without changing the start and end value individually (by holding the blue region of the slider bar). However, when I have implemented this feature, users have complained that this functionality is not obvious.
To make this functionality more obvious, I would like the cursor to change to a 'move' symbol e.g. when the the cursor hovers over the blue region.
Here is some simple code to modify.
library(shiny)
ui <- fluidPage(
sliderInput(inputId = 'slider1',
label = 'slider input',
min = 0, max =100,
value = c(10,90)
)
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)
I don't think you will be able to do this.
library(shiny)
ui <- fluidPage(
tags$style(
'#test {
cursor: crosshair;
color: red;
}'
),
div(id="test",sliderInput(inputId = 'slider1',
label = 'slider input',
min = 0, max =100,
value = c(10,90))
)
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)
This code changes the cursor inside a div with the slider, and the cursor still reverts to the special shiny slider cursor when you hover over the blue bar. In the shiny source code there is already a unique cursor programmed for the slider, so I don't think you will be able to override that, at least not easily.
Related
I am interested in removing or hiding the side arrows that appear when you use numericInput() with shiny. I will attach an image of the arrows that I am referring to so everyone can understand which part I would like to remove/hide. After reading the documentation, it does not appear that there is an option to remove these arrows. So I am wondering if there is a way to use CSS to remove these arrows. I did see one other post that asked a similar question. However, I am only interested in using numericInput().
I will attach some sample code. The code essentially does nothing but it will give you a reproducible example.
library(shiny)
server <- function(input, output){
}
ui <- fluidPage(
titlePanel("Test1"),
sidebarLayout(
sidebarPanel(
numericInput("n",
label = h4("Test2"),
min=1,
value = 20),
numericInput("x",
label = h4("Test3"),
min=0,
value = 10),
h4(textOutput("pvalue"))
),
mainPanel(
plotOutput("nullplot")
)
)
)
shinyApp(ui = ui, server = server)
runApp()
WARNING: I have read online that the side arrows do not show up on all web browsers and some versions of RStudio. See here
It does not appear that there is a way to remove the arrows from a numericInput(), however, there is a way to hide them. Just to be clear there is a difference between removing and hiding. Removing the arrows, in theory, should completely remove the code for the arrows. Hiding the arrows will simply mask the code for the side arrows, however, the code will still be present but will not be seen by the user unless they inspect the page.
Below is CSS that can be used to hide the side arrows from numericInput().
tags$head(
tags$style(HTML("
input[type=number] {
-moz-appearance:textfield;
}
input[type=number]::{
-moz-appearance:textfield;
}
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
"))
)
If you wanted to apply this code to the example given in the question, then you could do something like this
library(shiny)
server <- function(input, output){
}
ui <- fluidPage(
titlePanel("Test1"),
sidebarLayout(
sidebarPanel(
tags$head(
tags$style(HTML("
input[type=number] {
-moz-appearance:textfield;
}
input[type=number]::{
-moz-appearance:textfield;
}
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
"))
),
numericInput("n",
label = h4("Test2"),
min=1,
value = 20),
numericInput("x",
label = h4("Test3"),
min=0,
value = 10),
h4(textOutput("pvalue"))
),
mainPanel(
plotOutput("nullplot")
)
)
)
shinyApp(ui = ui, server = server)
runApp()
Overall this is just a workaround because there is no option to remove the side arrows.
I need to refresh data displayed in an infobox on a regular interval, but every time it updates it renders a new infobox making for an undesirable user experience.
I've tried using futures/promises for async processing but the renderinfobox still renders a new box on data update. Here's my code :
invalidateLater(30000)
results <-future({testFuture()})
return(value(results))
I would like to be able to update the underlying data of the infobox without dimming the ui element for the entire duration of the query.
Instead of re-rendering the infobox everytime the value changes, you can re-render just the title or the value of the infobox as I have shown by creating an output element. I have created an working example that refreshes the infobox to show current time at seconds level.
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Test App"),
dashboardSidebar(),
dashboardBody(
infoBox("TestBox", value = textOutput("currentTime"), subtitle = NULL,
icon = shiny::icon("bar-chart"), color = "aqua", width = 4,
href = NULL, fill = FALSE)
)
)
server <- function(input, output, session) {
output$currentTime <- renderText({
invalidateLater(1000, session)
paste(Sys.time())
})
}
shinyApp(ui = ui, server = server)
Do try out your code with this and let me know if this helps!
I am working on a shiny app, that reads data from a file, and display the data on the app, and also allows user to refresh the data. The app works fine, except that when I 'refresh' the data with the action button, some styling are gone.
Below is a simplified version of my app.R
library(shiny)
file_name <- "sample.csv"
bkg_color <- "red"
# Define UI for application
ui <- fluidPage(
actionButton("refresh", "", icon("refresh") ),
tableOutput("table"),
uiOutput("slider")
)
# Define server logic required
server <- function(input, output, session) {
observeEvent(input$refresh,{
source("updatedata.R")
showModal(modalDialog(
title = "",
"Data refreshed",
easyClose = TRUE,
footer = NULL
))
})
# observe the raw file, and refresh if there is change every 5 seconds
raw <- reactivePoll(5000, session,
checkFunc = function(){
if (file.exists(file_name))
file.info(file_name)$mtime[1]
else
""
},
valueFunc = function(){
read.csv(file_name)
})
output$table <- renderTable(raw())
output$slider <- renderUI({
req(raw())
tagList(
# styling slider bar
tags$style(HTML(paste0(".js-irs-0 .irs-single, .js-irs-0 .irs-bar-edge, .js-irs-0 .irs-bar {background: ",
bkg_color,";border-top: ",bkg_color,";border-bottom: ",bkg_color,"; border: ",bkg_color,"}"))),
sliderInput("date","",
min = min(raw()$v1),
max = max(raw()$v1),
value = max(raw()$v1))
)
})
}
# Run the application
shinyApp(ui = ui, server = server)
In the above, I used renderUI for my slider, as the values depends on the raw values I read from the local file. And I specify the color for the slider explicitly (currently set to red).
And in the same directory, I have updatedata.R that does something similar to the below:
file_name <- "sample.csv"
temp <- data.frame(v1 =runif(10, min = 0, max = 100), v2 = Sys.time() )
write.csv(x =temp, file = file_name,row.names = FALSE )
To run the sample app without error, please run the above code first to initialize the csv files.
When the app first launches, the slider bar is red color. However, after I refresh the underlying data by clicking on the refresh button at the top of the app [NOT the browser refresh], the slider bar changed back to the default shiny app color.
I've searched for an answer for this for quite some time, but cannot even figure out what is the root cause for this. Does anyone has experienced similar issue before, or have an idea how I can fix it, so that the color of the slider bar is unchanged after the refresh?
Thank you!
Shiny increments the slider class each time a new slider is rendered.
therefore the initial class becomes .js-irs-1 on refresh, then .js-irs-2 etc.
change your css selector to .irs child as follows:
tags$style(HTML(paste0(".irs .irs-single, .irs .irs-bar-edge, .irs .irs-bar {background: ",
bkg_color,";border-top: ",bkg_color,";border-bottom: ",bkg_color,"; border: ",bkg_color,"}")))
however i would recommend using server side logic to update the input. It's usually better practice since the html element is rendered on website and only certain values are updated not the whole element.
check updateSliderInput() function to update your slider
I'm creating a Shiny app in which I want to have a large (h1) formatted title and an action button right next to it, which when clicked on pops up a window with additional details and some other information. I got the button set up and working well (not included in the code). My problem is with the formatting of this line. Despite my best efforts the icon (an action button) gets pushed to a new row, even though it's in the same column as the dynamic text, and in the same h1 format as well. How could I achieve what I want?
library(shiny)
ui <- fluidRow(column(12, tags$h1(textOutput("chosen_date_fact"),
actionButton("scoping2",
label = icon("info-circle"),
style = "color: #000000; background-color: #ffffff; border-color: #ffffff"))))
server = function(input, output){
last_fact_date = '2017-07-16'
output$chosen_date_fact = renderText ({
date = as.Date(last_fact_date)
paste0('Details of', ' ', format(date,"%B"),' ', '(as of: ', date,')')
})
}
shinyApp(ui = ui, server = server)
Picture of the result: https://i.stack.imgur.com/gmhNM.jpg
Thank you in advance!
Something like this? Fore more examples visit another question i answered How to display widgets inline in shiny
library(shiny)
ui <- fluidRow(column(12, div(style="display: inline-block;",tags$h1(textOutput("chosen_date_fact"))),
actionButton("scoping2", label = icon("info-circle"), style = " color: #000000; background-color: #ffffff; border-color: #ffffff")
))
server = function(input, output){
last_fact_date = '2017-07-16'
output$chosen_date_fact = renderText ({
date = as.Date(last_fact_date)
paste0('Details of', ' ', format(date,"%B"),' ', '(as of: ', date,')')
})
}
shinyApp(ui = ui, server = server)
This is a bit minor, but after clicking an action button (normally light gray) in a Shiny app, it turns a darker gray and the focus remains on it. The user has to click somewhere else for the action button to return to its normal lighter color.
Try it out here: http://shiny.rstudio.com/gallery/actionbutton-demo.html
The lack of automatically reverting to a lighter color means the user doesn't get a visual feedback that the button was successfully pressed.
Is there a way to fix this?
Another way of doing it is by disabling the button while the process is running, it will also prevent people from re-clicking it while you are waiting on the result. Have a look at shinyjs package which has a lot of nice features. Note that I added 2 second delay to mimic long operation.
rm(list=ls())
library(shinyBS)
library(shiny)
library(shinyjs)
ui <- pageWithSidebar(
headerPanel("actionButton test"),
sidebarPanel(numericInput("n", "N:", min = 0, max = 100, value = 50),
tags$div(style="display:inline-block",title="Push Me",bsButton("goButton", label = "Button", block = TRUE,style="primary"))
),
mainPanel(useShinyjs(),verbatimTextOutput("nText")
)
)
server <- shinyServer(function(input, output,session) {
ntext <- eventReactive(input$goButton, {
shinyjs::disable("goButton")
Sys.sleep(2)
shinyjs::enable("goButton")
input$n
})
output$nText <- renderText({ntext()})
})
shinyApp(ui = ui, server = server)
Disabled Button
Enabled Button
You can tell the webbrowser to unfocus the actionbutton, when it is clicked. This way, you don't get the effects you describe. Below is a (more or less) two line JavaScript call to achieve this. The script reads very straightforward. When the document is ready, we add a functionality, that if a button is clicked, then it is blurred immediately (looses focus).
library(shiny)
ui <- shinyUI(pageWithSidebar(
headerPanel("actionButton test"),
sidebarPanel(
tags$script(HTML("
$(document).ready(function() {
$('.btn').on('click', function(){$(this).blur()});
})
")),
numericInput("n", "N:", min = 0, max = 100, value = 50),
br(),
actionButton("goButton", "Go!"),
p("Click the button to update the value displayed in the main panel.")
),
mainPanel(
verbatimTextOutput("nText")
)
))
server <- function(input, output) {
# builds a reactive expression that only invalidates
# when the value of input$goButton becomes out of date
# (i.e., when the button is pressed)
ntext <- eventReactive(input$goButton, {
input$n
})
output$nText <- renderText({
ntext()
})
}
shinyApp(ui, server)