From bce2bd2dc088d767032b483d1fabc85ad4085558 Mon Sep 17 00:00:00 2001 From: Dean Attali Date: Mon, 9 May 2016 23:39:51 -0700 Subject: [PATCH] add many readmes and a few more examples --- README.md | 150 +------------------------ auto-kill-app/README.md | 7 ++ auto-kill-app/app.R | 7 ++ busy-indicator/app.R | 98 ++++++++++++++++ busy-indicator/www/ajax-loader-bar.gif | Bin 0 -> 723 bytes close-window/README.md | 7 ++ close-window/app.R | 17 +++ error-custom-message/app.R | 19 ++++ select-input-large/README.md | 5 + select-input-large/app.R | 15 +++ server-to-ui-variable/app.R | 18 +++ shinydashboard-sidebar-hide/app.R | 4 +- simple-toggle/README.md | 5 + simple-toggle/app.R | 14 +++ upload-file-names/app.R | 35 ++++++ url-inputs/README.md | 5 + url-inputs/app.R | 18 +++ 17 files changed, 275 insertions(+), 149 deletions(-) create mode 100644 auto-kill-app/README.md create mode 100644 auto-kill-app/app.R create mode 100644 busy-indicator/app.R create mode 100644 busy-indicator/www/ajax-loader-bar.gif create mode 100644 close-window/README.md create mode 100644 close-window/app.R create mode 100644 error-custom-message/app.R create mode 100644 select-input-large/README.md create mode 100644 select-input-large/app.R create mode 100644 server-to-ui-variable/app.R create mode 100644 simple-toggle/README.md create mode 100644 simple-toggle/app.R create mode 100644 upload-file-names/app.R create mode 100644 url-inputs/README.md create mode 100644 url-inputs/app.R diff --git a/README.md b/README.md index 6fe7a60..7363d4f 100644 --- a/README.md +++ b/README.md @@ -1,148 +1,4 @@ -R shiny tricks (shinyjs - reset inputs, disable textinput when radio button is selected, loading..., state variables to use in ui - can be useful if want to use conditionalPanel with a variable that's calcualted in the server, global.R, splitting off big ui/server into files, shiny debugging such as add a `options(warn=2)` at top of UI and server if getting a "ERRORR: canot open the conenction" butyou have no clue where the error's happening or what file it's failing at, how to do toggle button (conditionalPanel with condition being input % 2 == 1) +R shiny tricks (shinyjs - reset inputs, disable, hide), global.R, +global.R, splitting off big ui/server into files -withBusyIndicator - -more breathing room in selectizeinput: - -``` -runApp(shinyApp( - ui = fluidPage( - tags$style(type='text/css', ".selectize-input { line-height: 40px; } .selectize-dropdown { line-height: 30px; }"), - selectInput("test","Test", 1:5) - ), - server = function(input, output, session) { - } -)) -``` - -fix uploaded file names - -``` -#' When files get uploaded, their new filenames are gibberish. -#' This function renames all uploaded files to their original names -#' @param x The dataframe returned from a shiny::fileInput -fixUploadedFilesNames <- function(x) { - if (is.null(x)) { - return() - } - - oldNames = x$datapath - newNames = file.path(dirname(x$datapath), - x$name) - file.rename(from = oldNames, to = newNames) - x$datapath <- newNames - x -} -``` - -show custom message when the'res an error in a reactive context - -``` -runApp(shinyApp( - ui = fluidPage( - tags$style(type="text/css", - ".shiny-output-error { visibility: hidden; }", - ".shiny-output-error:before { visibility: visible; content: 'An error occurred. Please contact the admin.'; }" - ), - textOutput("text") - ), - server = function(input, output, session) { - output$text <- renderText({ - stop("lalala") - }) - } -)) -``` - -prepopulate input fields when app loads - -``` -runApp(shinyApp( - ui = fluidPage( - textInput("name", "Name"), - numericInput("age", "Age", 25) - ), - server = function(input, output, session) { - observe({ - query <- parseQueryString(session$clientData$url_search) - if (!is.null(query[['name']])) { - updateTextInput(session, "name", value = query[['name']]) - } - if (!is.null(query[['age']])) { - updateNumericInput(session, "age", value = query[['age']]) - } - }) - } -)) -``` - -when developing shiny app , its annoying that when you close the browser window the app is still alive. - -``` -runApp(shinyApp( - ui = (), - server = function(input, output, session) { - session$onSessionEnded(function()stopApp()) - } -)) -``` - -click button to close the current window - -``` -library(shinyjs) -jscode <- "shinyjs.closewindow = function() { window.close(); }" - -runApp(shinyApp( - ui = tagList( - useShinyjs(), - extendShinyjs(text = jscode), - navbarPage( - "test", - id = "navbar", - tabPanel(title = "tab1"), - tabPanel(title = "", value = "Stop", icon = icon("power-off")) - ) - ), - server = function(input, output, session) { - observe({ - if (input$navbar == "Stop") { - js$closewindow(); - stopApp() - } - }) - } -)) -``` - -remove tooltip in ggvis - -``` -library(shiny) -library(ggvis) - -jscode <- -"$(function() { - $('#ggvis').click(function(){ $('#ggvis-tooltip').hide(); }); -}) -" - -shinyApp( - ui = fluidPage( - tags$script(jscode), - uiOutput("ggvis_ui"), - ggvisOutput("ggvis") - ), - server = function(input, output, session) { - mtcars %>% - ggvis(~wt, ~mpg) %>% - layer_points() %>% - add_tooltip(function(df) df$wt, on = "click") %>% - bind_shiny("ggvis", "ggvis_ui") - } -) -``` - -link to specific tab in app (simple vs complex: complex code is [here](https://github.com/rstudio/shiny/issues/772#issuecomment-112919149)) - -save all inputs in a shiny app and load them again (joe has a solution and ther's also shinyStore, but this is another solution) [here](http://stackoverflow.com/questions/32922190/saving-state-of-shiny-app-to-be-restored-later/32928505#32928505) (if using shinyjs reset, then it's safe to filter inputs by name, filter out ones with the prefix "shinyjs-") +show custom message when the'res an error in a reactive context \ No newline at end of file diff --git a/auto-kill-app/README.md b/auto-kill-app/README.md new file mode 100644 index 0000000..bef2abc --- /dev/null +++ b/auto-kill-app/README.md @@ -0,0 +1,7 @@ +# Automatically stop a Shiny app when closing the browser tab + +*Dean Attali, July 2015* + +When developing a Shiny app and running the app in the browser (as opposed to inside the RStudio Viewer), it can be annoying that when you close the browser window, the app is still running and you need to manually press "Esc" to kill it. By adding a single line to the server code `session$onSessionEnded(stopApp)`, a Shiny app will automatically stop whenever the browser tab (or any session) is closed. + +Note that this can be useful for local development, but you should be very careful not to deploy this code in a real server because you don't want your real Shiny app to stop every time a user leaves the app. \ No newline at end of file diff --git a/auto-kill-app/app.R b/auto-kill-app/app.R new file mode 100644 index 0000000..1f461e3 --- /dev/null +++ b/auto-kill-app/app.R @@ -0,0 +1,7 @@ +ui <- fluidPage() + +server <- function(input, output, session) { + session$onSessionEnded(stopApp) +} + +shinyApp(ui, server) \ No newline at end of file diff --git a/busy-indicator/app.R b/busy-indicator/app.R new file mode 100644 index 0000000..b8ad9e7 --- /dev/null +++ b/busy-indicator/app.R @@ -0,0 +1,98 @@ +library(shiny) +library(shinyjs) + +withBusyIndicatorServer <- function(buttonId, expr) { + loadingEl <- sprintf("[data-for-btn=%s] .btn-loading-indicator", buttonId) + doneEl <- sprintf("[data-for-btn=%s] .btn-done-indicator", buttonId) + errEl <- sprintf("[data-for-btn=%s] .btn-err", buttonId) + disable(buttonId) + show(selector = loadingEl) + hide(selector = doneEl) + hide(selector = errEl) + on.exit({ + enable(buttonId) + hide(selector = loadingEl) + }) + + tryCatch({ + value <- expr + show(selector = doneEl) + delay(2000, hide(selector = doneEl, anim = TRUE, animType = "fade", + time = 0.5)) + value + }, error = function(err) { errorFunc(err, buttonId) }) +} + +errorFunc <- function(err, buttonId) { + errEl <- sprintf("[data-for-btn=%s] .btn-err", buttonId) + errElMsg <- sprintf("[data-for-btn=%s] .btn-err-msg", buttonId) + cat(errElMsg) + errMessage <- gsub("^ddpcr: (.*)", "\\1", err$message) + html(html = errMessage, selector = errElMsg) + show(selector = errEl, anim = TRUE, animType = "fade") +} + +# Set up a button to have an animated loading indicator and a checkmark +# for better user experience +# Need to use with the corresponding `withBusyIndicator` server function +withBusyIndicatorUI <- function(button) { + id <- button[['attribs']][['id']] + div( + `data-for-btn` = id, + button, + span( + class = "btn-loading-container", + hidden( + img(src = "ajax-loader-bar.gif", class = "btn-loading-indicator"), + icon("check", class = "btn-done-indicator") + ) + ), + hidden( + div(class = "btn-err", + div(icon("exclamation-circle"), + tags$b("Error: "), + span(class = "btn-err-msg") + ) + ) + ) + ) +} + +ui <- fluidPage( + useShinyjs(debug=T), + tags$style(".btn-loading-container { + margin-left: 10px; + font-size: 1.2em; + } +.btn-done-indicator { + color: green; + } + + .btn-err { + margin-top: 10px; + color: red; + }"), + selectInput("select", "Select an option", + c("This one is okay" = "ok", + "This will give an error" = "error")), + withBusyIndicatorUI( + actionButton( + "uploadFilesBtn", + "Process data", + class = "btn-primary" + ) + ) +) + +server <- function(input, output, session) { + observeEvent(input$uploadFilesBtn, { + withBusyIndicatorServer("uploadFilesBtn", { + Sys.sleep(1) + if (input$select == "error") { + stop("choose another option") + } + }) + }) +} + +shinyApp(ui = ui, server = server) \ No newline at end of file diff --git a/busy-indicator/www/ajax-loader-bar.gif b/busy-indicator/www/ajax-loader-bar.gif new file mode 100644 index 0000000000000000000000000000000000000000..09d621ede9dbe610877292e554c858d60573359e GIT binary patch literal 723 zcmZ?wbhEHb6ky3UH!ouR`=lAT{vl};VeEIUl!ouRtojadCecHBd+kyoPPMtdS z?%g|}ArPSWpWDwhB-q(8z|~04fSC~}s`yXJxhOTUBsE2$JhLQ2Au%hlA}2pFMK3ci zEuTU0CkrPxP?ZiyKgf{`thx#ceJPpqmMq|Ubc$)6gFv&z8PkHx)%R}in9s-lM6i9! zBZm__dd2Imak;LY=7h}zm4rkI)`WR0GG*E)?mKYn(8@QLmiIn?v-kDx2z`w?tc})! zof1sgG@1de?oQNs+@Zp$B*l}wBx#YxN$K-jdS4q!9hlC1plNUP#}nRyjb|@j-XZKa z^H3#V%=s`!CV{ zGZTv~S)?jgU+dnbH8)5Rn@L8H@VK@q;+ad}wo4-xl69peI z>rMAn>7QZ36tBx*W_EhPz6U`Z*qo#fG3yD?Ju5c7TU8{Z8nlJ?f$93++hq!-bARhP dGOMsv=2x69g9)2+