Hello!
I have some questions regarding reactivity (I think). I have a shiny app with multiple tabs. The first tab takes an upload of terms from the user, then searches those keywords in elastic when clicking search, which is all in a function keyword_search
-- my issue is, once the function returns a dataframe, that dataframe is the input to a global.R ( text_global.R
) that I need to not run until a user clicks a run button, because otherwise the data it needs is not available until the keyword_search
function is completed and the app will error out. Another issue because of that is that the global.R is stuck inside an eventReactive
and thus I'm not sure if that hinders the ability to use all of the variables created from that file in the rest of my renderPlots.
I understand that having text_global.R
inside of eventReactive
containerizes it from using it in other portions of server
, but if I take it out and make it actually global then it runs right when the session starts, and that just makes my app error out because the data it needs does not exist until the keyword_search
function is run. I tried to make the eventReactive
into a callable function with adding data() <-
in front of it and trying to use data() as the input to the text_global.R
, but it wouldn't work.
Here is my shiny code and what I'm trying right now (sorry its long but wanted to give context):
ui <- navbarPage("App", theme = shinytheme("united"),
tabPanel("Search Your Terms",
titlePanel("Welcome"),
br(),
br(),
mainPanel("Please upload .XLSX file of the terms that you would like searched.",
br(),
br(),
"When you hit the search button, the code will pull the data, then you can navigate to the next tabs to run each type of analysis.",
br(),
br(),
fileInput('file1', 'Choose .xlsx file of terms:',
accept = c(".xlsx")),
actionButton("srch", "Search"),
tableOutput('contents'))),
tabPanel("Text Analysis",
titlePanel("Word Analysis"),
tabsetPanel(
tabPanel("Word Cloud",
sidebarPanel(width = 2,
actionButton("runtext", "Run Text Analysis"),
column(width = 10, align='center',
sliderInput("cloudsize", "Choose size (larger size shows more words)", min = .1, max = .9, value = .8, step = .1),
wordcloud2Output('wcplot', height = '500px'))),
tabPanel("Word Counts",
column( width = 10,
uiOutput("data1"),
plotOutput('counts'),
dataTableOutput("wordcount_dt"))),
tabPanel("Common Word Sequence",
column( width = 10,
uiOutput("data2"),
plotOutput('bigrams'),
dataTableOutput("bigram_dt")))
)),
tabPanel("Topic Modeling",
titlePanel("Topics"),
mainPanel(width = 10,
plotOutput("topics"),
dataTableOutput("topiccontents"))),
tabPanel("Social Network Analysis",
sidebarPanel(actionButton("netsrch", "Get"),
actionButton("runnet", "Create"),
width = 2),
mainPanel(visNetworkOutput("network"),
dataTableOutput("netdt")
))
)
server <- function(input, output) {
output$contents <- renderTable({
req(input$file1)
inFile <- input$file1
read_excel(inFile$datapath, 1)
})
source('keyword_search.R')
observeEvent(input$srch, {
inFile <- input$file1
file <- read_excel(inFile$datapath, 1)
file <- na.omit(file)
keyword_search(file)
showModal(modalDialog("Search finished, head to the next tab!"))
})
#this text_global.R has variables that are used for over half of my app, how #do I make its contents available for everything WITHOUT having it run the #moment the session starts?
eventReactive(input$runtext, {
source('text_global.R')
})
output$data1 <- renderUI({
selectInput("data1", "Choose which you would like to view:", choices = c(tfdf_forplot$report_name))
})
output$wcplot <- renderWordcloud2({
wordcloud2(forwordcloud2, size = (input$cloudsize), color = rep_len( c("orange", "teal", "gray"), nrow(forwordcloud2)))
})
output$counts <- renderPlot({
ggplot(tfdf_forplot[tfdf_forplot$report_name==input$reportchoose,]) + (aes(word, tf_idf)) +
geom_col(show.legend = FALSE, fill = '#cc3300', alpha = .9) +
labs(x = NULL, y = "tf-idf") +
coord_flip() +
theme_hc()
})
output$wordcount_dt <- renderDataTable({
datatable(tidy_output, colname = c("Report Name", "Word", "Count of Word", "Total Words", "tf", "idf", "tf_idf"))
})
output$data2 <- renderUI({
selectInput("data2", "Choose which device you would like to view:", choices = c(bigram_forplot$report_name))
})
output$bigrams <- renderPlot({
ggplot(bigram_forplot[bigram_forplot$report_name==input$reportchoose2,]) + aes(bigram, tf_idf, fill = report_name) +
theme(text = element_text(size=6)) +
geom_col(show.legend = FALSE, fill = '#cc3300', alpha = .9) +
labs(x = NULL, y = "tf-idf") +
coord_flip() +
theme_hc()
})
output$bigram_dt <- renderDataTable({
bigram_tf_idf
})
output$topics <- renderPlot({
ggplot(top_terms) + aes(term, beta, fill = factor(topic)) +
theme(text = element_text(size=10)) +
geom_col(show.legend = FALSE, fill = '#cc3300', alpha = .9) +
facet_wrap(~ topic, scales = "free") +
coord_flip()
})
output$topiccontents <- renderDataTable({
report_contents
})
eventReactive(input$runnet, {
source('sna_global.R')
})
output$network <- renderVisNetwork({
visIgraph(g2, idToLabel = TRUE) %>%
visOptions(highlightNearest = list(enabled = TRUE, labelOnly=FALSE,
degree=list(from = 1, to = 1), algorithm="hierarchical"),nodesIdSelection = TRUE)
})
source('report_search.R')
observeEvent(input$netsrch, {
report_search()
showModal(modalDialog("Network is Ready!"))
})
output$netdt <- renderDataTable({
datatable(nodelist, rownames = FALSE,
filter = 'top', extensions = 'Buttons',
options = list(columnDefs = list(list(className = 'dt-center', targets = c(0:3))),
pageLength = 10, dom = 'Bfrtip', buttons = c('copy', 'csv', 'excel', 'pdf', 'print')))
})
}
shinyApp(ui = ui, server = server)
I just keep getting "not found" errors for everything in my global.R file where the renderPlots
should be. Any advice would be greatly appreciate with how to work with the output of the eventReactive
and using it in the global.R, but also making it so the global.R is accessible to the rest of the server components but doesn't run until a button is clicked. Sorry, I know that's a complicated ask. I hope I explained it alright
And all of this works outside of the shiny app so I know the code itself in the global.R is right.
UPDATE: I am using req()
now for the plots that depend on text_global.R, so now those don't show errors until the Run Text Analysis button is clicked, but still haven't figured out how to use the observeEvent
function output in the text_global.R.