I am trying to make an Shiny app which takes input from user in textInput. I want text inside the textbox to be clear when it is clicked on. I could find solutions only for clicked on button. I need a mouse event for clicking on text box.
Do you have any idea about it?
This can be achieved through the shinyjs onclick function like so:
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
fluidRow(
textInput(inputId = "text_input", label = "Example Text Input", value = "Click me to clear")
)
)
server <- function(input, output) {
shinyjs::onclick(id = "text_input", expr = updateTextInput(inputId = "text_input", value = ""))
}
# Run the application
shinyApp(ui = ui, server = server)
Related
In order to make an app where panels are created dynamically, I would like to remove, hide and/or update panels from the package shinyWidgets.
I didn't find any function to do so nor way to add IDs to these panel.
If you have the solution or a way around, I would be more than happy. Thank you in advance !
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
panel(
heading = "Test panel",
actionButton("remove_panel", "Remove this panel")
)
)
server <- function(input, output) {
observeEvent(input$remove_panel,{
print("remove panel")
})
}
shinyApp(ui = ui, server = server)
There is no official method you can use to change the panel states, but we can do it with custom expressions.
library(shiny)
library(shinyWidgets)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
panel(
heading = "Test panel1",
id = "test_panel1",
actionButton("remove_panel", "Remove this panel")
),
panel(
heading = "Test panel2",
id = "test_panel2",
"some content"
),
actionButton("hide_panel", "Hide this panel")
)
server <- function(input, output) {
observeEvent(input$remove_panel,{
removeUI('.panel:has([id="test_panel1"])', immediate = TRUE)
})
observeEvent(input$hide_panel,{
toggle(selector = '.panel:has([id="test_panel2"])')
if(input$hide_panel %% 2 == 1) return(updateActionButton(inputId = "hide_panel", label = "Show this panel"))
updateActionButton(inputId = "hide_panel", label = "Hide this panel")
})
}
shinyApp(ui = ui, server = server)
To remove:
add an ID argument to your panel, and use removeUI to remove it. Remember to change the ID in you own case.
To hide/show:
We can use toggle from shinyjs to show or hide some elements we choose.
Use updateActionButton to also change it text when hidden.
I have a Shiny App that has a button that runs a quite long (around 30 minutes) routine. what I would like to do is to disable the button that calls the process once the user clicks on it and that the button can be 'clickable' again once the process finishes...
Ideally I would click on the Action Button and it gets disabled, its label changes to 'Running' and once the process ends the button is clickable again and the label goes back to 'Run Process'.
So:
User clicks on an action button labeled "Run"
Button changes label to "Running" and is no longer clickable
Process Finishes
Button is clickable again and label goes back to "Run"
Thx
Basic shiny has update functions, such as updateActionButton(). You can use it to update the label:
updateActionButton(inputId = "run_button", label = "Running...")
As for disabling and enabling buttons, look into shinyjs library - it provides functions for a lot of this sort of stuff.
That depends on what happens when you click the button. Here is an example where clicking the button runs a time-consuming plot.
library(shiny)
js <- '
$(document).ready(function(){
$("#myplot").on("shiny:recalculating", function(){
$("#run").prop("disabled", true).text("Running...");
}).on("shiny:recalculated", function(){
$("#run").prop("disabled", false).text("Run");
});
})
'
ui <- fluidPage(
tags$head(
tags$script(HTML(js))
),
br(),
actionButton("run", "Run", class = "btn-primary btn-lg"),
br(),
plotOutput("myplot")
)
server <- function(input, output, session){
output[["myplot"]] <- renderPlot({
if(input[["run"]] > 0){
x <- y <- NULL
for(. in 1:25000){
x <- c(x, runif(1))
y <- c(y, runif(1))
}
plot(x, y)
}
})
}
shinyApp(ui, server)
And you can add a spinner with the shinybusy package:
library(shiny)
library(shinybusy)
js <- '
$(document).ready(function(){
$("#myplot").on("shiny:recalculating", function(){
$("#run").prop("disabled", true).text("Running...");
}).on("shiny:recalculated", function(){
$("#run").prop("disabled", false).text("Run");
});
})
'
ui <- fluidPage(
tags$head(
tags$script(HTML(js))
),
add_loading_state(
"#myplot",
spinner = "hourglass",
svgSize = "100px"
),
br(),
actionButton("run", "Run", class = "btn-primary btn-lg"),
br(),
plotOutput("myplot")
)
I have a reset (actionButton) and update button (submitButton) in my Shiny app. The problem is that to reset the app, I have to click on the reset button followed by the update button. Is it possible to reset the app without having to click on update?
EDIT: I do want the app to update only after the user explicitly clicks update. This is because in my app they will have the option to select several selectors to filter the data. Happy to use something else other than submitbutton, but so far this has been the only function that worked for the purpose.
In the example below, I have to click on update twice to get the whole app to reset :
library(shiny)
shinyApp(
ui = basicPage(
numericInput("num", label = "Make changes", value = 1),
submitButton("Update", icon("refresh")),
shinyjs::useShinyjs(),
actionButton("reset", "Reset"),
helpText(
"When you click the button above, you should see",
"the output below update to reflect the value you",
"entered at the top:"
),
verbatimTextOutput("value")
),
server = function(input, output) {
# submit buttons do not have a value of their own,
# they control when the app accesses values of other widgets.
# input$num is the value of the number widget.
output$value <- renderPrint({
input$num
})
observeEvent(input$reset, {
shinyjs::reset("num")
})
}
)
I hope someone can enlighten me!
Perhaps actionButton in combination with updateNumericInput() will meet your needs. Try this
library(shiny)
shinyApp(
ui = basicPage(
numericInput("num", label = "Make changes", value = 1),
actionButton("Update", "refresh"),
shinyjs::useShinyjs(),
actionButton("reset", "Reset"),
helpText(
"When you click the button above, you should see",
"the output below update to reflect the value you",
"entered at the top:"
),
verbatimTextOutput("value")
),
server = function(input, output,session) {
# submit buttons do not have a value of their own,
# they control when the app accesses values of other widgets.
# input$num is the value of the number widget.
observeEvent(input$Update, {
output$value <- renderPrint({
isolate(input$num)
})
})
observeEvent(input$reset, {
#shinyjs::reset("num")
updateNumericInput(session,"num",value=1)
})
}
)
I have a dataTableOutput in my main panel. Then I have an action button "Go". Once I click "Go" I want rHandsOutput to appear in the main panel but not beneath dataTableOutput. How can I remove dataTableOutput in the main panel and display rHandsOutput. In my current code both tables appearing together. Once I click "Go", the second table comes under the first table where I want to appear only second table (rHandsOutput) removing 1st table from the main panel.
Please help me!1
You can use a combination of insertUI and removeUI to make UI components dynamic. For example:
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
actionButton(inputId = "go", label = "Go")
),
mainPanel(
fluidRow(
tags$div(id = "firstOutput",
dataTableOutput("myDataTable"))
),
fluidRow(
tags$div(id = "placeholder") # the dynamic UI will be inserted relative to this placeholder
)
))
)
server <- function(input, output) {
output$myDataTable <- renderDataTable(iris)
observeEvent(input$go, {
removeUI("div:has(>#firstOutput)")
insertUI(
selector = "#placeholder",
where = "afterEnd", # inserts UI after the end of the placeholder element
ui = fluidRow(
actionButton(inputId = "newButton", label = "A new button")))
})
}
shinyApp(ui = ui, server = server)
You can use showElement() and hideElement() from shinyjs:
observeEvent(input$go, {
shinyjs::hideElement(“firsttable”)
shinyjs::showElement(“rHandsOutput”)
})
Assuming the ID of the first table is “firsttable” and the ID of the second table is “rHandsOutput”, and the ID of the “Go” button is “go”.
Generate the ui dynamically.
Use uiOutput("someidentifier") in the ui.r and then fill it with your datatable with the following in server.r
output$someidentifier <-
renderUI({
dataTableOutput("datatableidentifier")
})
output$datatableidentifier <- renderDataTable(iris)
uiOutput takes the place (in ui.r) of whatever ui element you want to add dynamically. The necessary code for that ui then moves to renderUI in server.r.
My objective is to create a ShinyApp that opens a new empty UI whenever user clicks on submitButton.
Currently this is my code below. If the user types something in the text box and press Submit. The app shows what the user typed in the main panel. However I dont want to see the text, instead when the user clicks on the submit button , it should open a new empty UI.
ui = shinyUI(fluidPage(
titlePanel("submitButton example"),
fluidRow(
column(3, wellPanel(
textInput("text", "Text:", "text here"),
submitButton("Submit")
)),
verbatimTextOutput("text")
)
)
)
server = function(input, output) {
output$plot1 <- renderPlot({
hist(rnorm(input$n))
})
output$text <- renderText({
paste("Input text is:", input$text)
})
}
shinyApp(ui=ui, server=server)
Is this possible ? Any tips or pointers are appreciated.
Well, this is not yet very functional, but does what you asked for.
ui = shinyUI(fluidPage(
titlePanel("submitButton example"),
fluidRow(
uiOutput("newWindowContent", style = "display: none;"),
tags$script(HTML("
$(document).ready(function() {
if(window.location.hash != '') {
$('div:not(#newWindowContent)').hide();
$('#newWindowContent').show();
$('#newWindowContent').appendTo('body');
}
})
")),
a(href = "#NEW", target = "_blank",
actionButton("Submit", "Submit")
)
))
)
server = function(input, output) {
output$newWindowContent <- renderUI({
"Welcome to your new window!"
})
}
shinyApp(ui=ui, server=server)
The app is created, such that the ui created in newWindowContent is displayed in the new window. Sadly, new windows are somewhat cut off from the parent page, such that there is no easy way to configure each page independently. At the moment, all show the same content. None have reactivity features. I guess there can be initial configurations, if one uses the window's hash. But this works only client sided.
Nevertheless, it's a good start!