shinydashboard: execute data import x seconds after pressing a button - r

BACKGROUND
I'm building a shiny dashboard in Data Science Studio where a user has to choose a file they want to process from the selectizeInput and then press Submit actionButton. Once the button is pressed, it starts a backend process to determine what category the file falls into and what workflow it should follow (different workflows contain different cleaning steps and final outputs). Once the workflow completes, I want to display the final output in DT::renderDataTable.
DESIRED OUTPUT
I would like my shiny app to
show no data before the input is chosen
time, let's say, 30 seconds from the moment someone clicks the Submit button to actually picking up the dataset
MINIMAL WORKING EXAMPLE
How could I implement it in this simple app?
UI
library(shiny)
library(shinydashboard)
library(DT)
library(dataiku)
path <- dkuManagedFolderPath("receiver") #folder with the files to choose from
dashboardPage(
dashboardHeader(title = "Catchy Title"),
dashboardSidebar(
selectizeInput("file", "Select File",
list.files(path)),
actionButton("submit", "Submit")
),
dashboardBody(
fluidRow(
box(h2("Show Data"),
div(style = 'overflow-x: scroll', DT::dataTableOutput('mytable')),
width = 12)
)
)
)
SERVER
library(dataiku)
library(shiny)
library(shinydashboard)
library(DT)
library(dplyr)
shinyServer(function(input, output) {
file_name <- reactive({
req(input$file)
})
####
# run the process that takes the file name to pass it to
# the global environment, which triggers the conditional workflow
# and may result in different data outputs
####
## AFTER the process runs (approx. 30 seconds after pressing the submit button)
# I want the shiny app to follow this logic:
if(is.null(nrow(try(dkuReadDataset("intermediate_dataset"))[1]))){
df <- dkuReadDataset("final_data1")
} else{
df <- dkuReadDataset("final_data2")
}
output$mytable = DT::renderDataTable({
df
})
})
Thanks for the hints!

Related

Is there a way to replace the texts in the textInput without clicking and using tabs?

Good day all,
I have created a dashboard for the scanning station whereby the operator is able to observe the details of the item after he or she scanned it with a barcode scanner. The issue I am currently facing is that I am unable to scan the barcode of the item without clicking on the textbox. Ideally, what I want to do is:
To allow the operator to scan the barcode straight away on the textbox without clicking on the textbox.
Automatically highlight the barcode number in the textbox so the next barcode number can be scanned and the details of the second item can be rendered.
Reproducible example:
ui.R
library(shiny)
library(shinydashboard)
library(shinyBarcode)
library(shinyjs)
dashboardPage(
dashboardHeader(title = "Barcode System"),
dashboardSidebar(collapsed = T),
dashboardBody(
useShinyjs(),
box(width = 4, height = 880,
shinyBarcode::includeJsBarcode(cdn = TRUE),
textInput("barcode_no", h3("Scan Barcode No")),
shinyBarcode::barcodeOutput("scanned_barcode")
)))
server.R
library(shiny)
library(shinydashboard)
library(shinyBarcode)
library(shinyjs)
shinyServer(function(input, output, session) {
# Rendering barcode
output$scanned_barcode<- shinyBarcode::renderBarcode(
paste("0",input$barcode_no, sep="") # Need to add "0" to all barcode at the front
)
})
Note: Here is how to install shinyBarcode
# install.packages("devtools")
devtools::install_github("CannaData/shinyBarcode")
If you are still unable to install, download the ZIP file from Github.
Next, openup the zip file and install using the following command:
devtools::install("C:\\Users\\dave\\Downloads\\shinyBarcode-master") # Edit to your download directory
Preview
Managed to find a solution:
Added this into my UI:
library(shiny)
library(shinydashboard)
library(shinyBarcode)
library(shinyjs)
dashboardPage(
dashboardHeader(title = "Barcode System"),
dashboardSidebar(collapsed = T),
dashboardBody(
# Added JS script
tags$head(tags$script("Shiny.addCustomMessageHandler('selectText', function(message) {
$('#barcode_no').select();
});")),
useShinyjs(),
box(width = 4, height = 880,
shinyBarcode::includeJsBarcode(cdn = TRUE),
textInput("barcode_no", h3("Scan Barcode No")),
shinyBarcode::barcodeOutput("scanned_barcode")
)))
Added this into the server.R
library(shiny)
library(shinydashboard)
library(shinyBarcode)
library(shinyjs)
shinyServer(function(input, output, session) {
# Rendering barcode
output$scanned_barcode<- shinyBarcode::renderBarcode(
paste("0",input$barcode_no, sep="") # Need to add "0" to all barcode at the front
)
observeEvent(input$barcode_no,{
session$sendCustomMessage("selectText", "select")
})
})
This has resolved 2 issues:
Upon starting up the app, the only way for us to key in the barcode number is by clicking or using Tab.
After the material number is added, the user will need to click or use tab in order to highlight the previous barcode number and replace it with the second barcode number.

How to make sure a button is pressed the first time a shiny app gets run?

So I have a set of computations that is generated when a button is pressed.
But I want the computation to be generated when the app is launched initially.
Which basically translates to having that button automatically pressed upon launch of the app.
How can that be done in R Shiny app?
Here's one way using shinyjs::click() function using which you can simulate a button click when app is initialized. Run the app with and without the observe to see the difference. -
library(shiny)
library(shinyjs)
init <- 5
shinyApp(
ui = fluidPage(
useShinyjs(),
br(),
actionButton("add", "Add"),
verbatimTextOutput("test")
),
server = function(input, output, session) {
o <- observe({
shinyjs::click("add")
o$destroy() # destroy observer as it has no use after initial button click
})
val <- eventReactive(input$add, {
init + 1
})
output$test <- renderPrint(val())
}
)

Run only relevant observe functions for each tab in shinyapp

In my shiny app I have several tabs as follows.
I have little complex functions running in this app. I think all the observe functions in the server function run when anything is done in any tab. So I need to run only relevant observe functions for relevant tab. As an example, when I am in Summary tab only the relevant observe function should run and all the other observe functions should not run. I have a code.
server <- function(input, output) {
summary <- observe({....})
occupancy<- observe({....})
Bookings<- observe({....})
Maps<- observe({....})
}
Is there any modification to the above code to run only the relevant observe function related to the tab opened in the app.?
Some approaches come to mind. But first; what do you want to do in your observers? If you are simply creating output to display to the user, don't forget to use reactive elements. They will automatically invalidate only when their output is used to display something to the user. Thus if reactive X uses input Y used to construct output for tab A, and input Y changes while we are looking at tab B, reactive X will not invalidate.
If you are using your observers to only create side-effects, such as updating inputs or showing modalDialogs, you could:
use observeEvent instead of observe to only listen to changes in a certain input or condition.
use isolate to make isolate certain dependencies.
build an if-statement in your observer, that checks which tab is selected. You can do that by giving your sidebarMenu an id (my_sidebarmenu in the example below), and check which tab is selected inside your observer by calling input$my_sidebarmenu.
Some examples given below, how this helps~
#UI.R
#loading shiny library
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(id='my_sidebarmenu',
menuItem('Tab 1', tabName='tab1'),
menuItem('Tab 2', tabName='tab2'),
actionButton(inputId = 'btn','Press me!')
)
),
dashboardBody(
tabItems(
tabItem('tab1',
p('Tab 1'),
actionButton('btn_tab1','Show message!')),
tabItem('tab2',
p('Tab 2'),
actionButton('btn_tab2','Show message!'))
)
)
)
server <- function(input, output,session)
{
observeEvent(input$btn,
{
if(input$my_sidebarmenu=='tab1')
{
updateTabItems(session,'my_sidebarmenu',selected='tab2')
}
if(input$my_sidebarmenu=='tab2')
{
updateTabItems(session,'my_sidebarmenu',selected='tab1')
}
})
observeEvent(input$btn_tab1,
{
showModal(modalDialog(
title = "One.",
"You are viewing tab 1!",
easyClose = TRUE,
footer = NULL
))
})
observeEvent(input$btn_tab2,
{
showModal(modalDialog(
title = "Two.",
"You are viewing tab 2!",
easyClose = TRUE,
footer = NULL
))
})
}
shinyApp(ui,server)

How to present an output without waiting for the rest of the script to run in R Shiny

I have a Shiny app that should calculate a value, present it and then use the same value for further more expensive computation. The problem is that it shows me the output only after it finishes evaluating the whole script. Here is a simple example:
library(shiny)
ui <- fluidPage(
titlePanel("test"),
sidebarLayout(
sidebarPanel(
textInput("text_in","Enter text here",value = "This is text to process"),
actionButton("go", "Go")
),
mainPanel(
textOutput("first_text"),
textOutput("results")
)
)
)
# Define server logic
server <- function(input, output) {
num_letter<-eventReactive(input$go, {
nchar(input$text_in)})
output$first_text <- renderText(num_letter())
sec_calculation<-eventReactive(num_letter(), {
Sys.sleep(3)
num_letter()*num_letter()})
output$first_text <- renderText(num_letter())
output$results <- renderText(sec_calculation())
}
# Run the application
shinyApp(ui = ui, server = server)
I added the Sys.sleep so it will be easier to see the problem. I would like to get the first output without waiting for the second one.
This is not currently possible (at least not with native shiny code - you can always hack a workaround). An open issue for this exists on the shiny github repository: https://github.com/rstudio/shiny/issues/1705

Stop functions starting in shiny until button pressed

I have begun to create a web app using shiny where a user enters a search term and tweets containing that term are returned.
When I load this app the searchTwitter function begins automatically and on the main panel there is the error: Error: You must enter a query.
The search term is entered in the textInput box and there is a submitButton. You can enter a term and it works fine but I don't want the error to be the first thing the user sees.
ui.R:
library(shiny)
shinyUI(pageWithSidebar(
headerPanel("Twitter Generator"),
sidebarPanel(
textInput("search", "Search Twitter For:", value = ""),
submitButton("Search")
),
mainPanel(
h3(textOutput("search")),
tableOutput("view"),
)
))
server.R:
library(shiny)
library(twitteR)
shinyServer(function(input, output) {
datasetInput <- reactive(function(){
rawTweets <- twListToDF(searchTwitter(paste(input$search)))
rawTweets$cleanText <- as.vector(sapply(rawTweets$text, CleanTweet))
rawTweets[, colnames(rawTweets) != "created"]
})
output$search <- reactiveText(function() {
input$search
})
output$view <- reactiveTable(function() {
head(datasetInput())
})
})
Thanks for your help
This is a logical request for and from your application design, and you should think through how to do it.
One easy way would be to add a tickbutton providing a true/false and to skip the actual twitter search if the value is FALSE. You may need to cache the previous value of rawTweets, or set it to NULL, or ...
mainPanel(
h3(textOutput("search")),
tableOutput("view")
)
try it without the second ","

Resources