How to use R Shiny reactive server objects in UI input widgets - r

I'm trying to have a Shiny app, that is connecting to a database, but the IP and so an can be modified by a User.
In short, I kind of just want to know, if its possible to have a shiny app, with objects from reactiv server parts included in the UI select inputs.
Like this:
library(shiny)
ui <- fluidPage(
selectizeInput(inputId = 'inSelect',
label = "countries",
choices = getTable(),
multiple = TRUE,
options = list(maxItems = 4,
placeholder = 'select up to 4 countries')
)
)
server <- function(input, output) {
getTable <- reactive({
country <- data.frame(name=c("Germany","France","Japan"),
code=c("DEU","FRA","JPN"))
countryN <- country$code
names(countryN) <- country$name
})
}
shinyApp(ui = ui, server = server)
when it works, it should look like this:
I know, that I can achieve this effect, by just building the DF before the UI, but my real problem is ab bit more complicated:
I want the user to type in IP, Username,PW, and DB name, to connect to the DB.
After a button click, the connection should be established and the df. country should be pulled out of the DB, not constructed.
I think, that I have to do this part in the (reactive) Server part, because I am using Input$x in the DB connection.
I hope, that my vision is somehow possible and you guys can help me,
Thanks.

you can use updateSelectInput() to update a select input from the server side of the app more info found here: https://shiny.rstudio.com/reference/shiny/1.2.0/updateSelectInput.html
in your specific example you can achieve this by:
library(shiny)
ui <- fluidPage(
selectizeInput(inputId = 'inSelect',
label = "countries",
choices = NA,
multiple = TRUE,
options = list(maxItems = 4,
placeholder = 'select up to 4 countries')
)
)
server <- function(input, output,session) {
getTable <- reactive({
country <- data.frame(name=c("Germany","France","Japan"),
code=c("DEU","FRA","JPN"))
countryN <- country$code
names(countryN) <- country$name
return(country)
})
observe({updateSelectInput(session, inputId="inSelect", label = NULL, choices = getTable()$name,
selected = NULL)})
}
shinyApp(ui = ui, server = server)
by adding the argument session to the server function and then using the updateSelectInput() function, this must be wrapped in a reactive expression in this example I used observe()

Related

Need help making dependent dropdown boxes in the RStudio package Shiny

I have two datasets, one with a list of two hundred cities and their corresponding state and another much larger dataset that I'd like to make an app to sort through. I need help making two drop down boxes in my shiny app where the first is the state variable and the second is the list of cities within that chosen state. I then want those selections to filter the much larger, second dataset in the output. I've tried solutions from several similar but slightly different examples online, but I'm having trouble translating it to what I'm doing.
So far I have this:
ui <- fluidPage(
headerPanel(''),
sidebarPanel(
#add selectinput boxs
htmlOutput("state_selector"),
htmlOutput("city_selector"),
),
mainPanel(
fluidRow(
# Create a new row for the table.
DT::dataTableOutput("table")
)
server <- function(session, input, output) {
output$state_selector = renderUI({
selectInput("state", label = h4("State"),
choices = as.character(unique(citystatedata$state)), selected = NULL)
})
output$city_selector = renderUI({
data_available = citystatedata[citystatedata$State == input$state, "state"]
selectInput(inputId = "city", #name of input
label = "City", #label displayed in ui
choices = unique(data_available), #calls list of available cities
selected = unique(data_available)[1])
})
shinyApp(ui = ui, server = server)
I tried to take out the portions of the code that weren't specifically related to the drop down boxes, since that's what I was more specifically asking about. So I'm sorry if I've left anything out! Let me know if I need to include anything else
Using available gapminder data, you can try this.
df <- gapminder
df$state <- gapminder$continent
df$city <- gapminder$country
citystatedata <- df
ui <- fluidPage(
headerPanel('Test'),
sidebarPanel(
#add selectinput boxs
uiOutput("state_selector"),
uiOutput("city_selector"),
),
mainPanel(
fluidRow(
# Create a new row for the table.
DTOutput("table")
)
)
)
server <- function(session, input, output) {
output$state_selector = renderUI({
selectInput("state", label = h4("State"),
choices = as.character(unique(citystatedata$state)), selected = NULL)
})
output$city_selector = renderUI({
data_available = citystatedata[citystatedata$state == req(input$state),]
selectInput(inputId = "city", #name of input
label = "City", #label displayed in ui
choices = unique(data_available$city), #calls list of available cities
selected = 1)
})
mydt <- reactive({
citystatedata %>% filter(citystatedata$state == req(input$state) & citystatedata$city %in% req(input$city))
})
output$table <- renderDT(mydt())
}
shinyApp(ui = ui, server = server)

Reactive function not being found within app

I have a fairly involved app. When I call a particular eventReactive function, let's call it function A, within a reactive expression, I get an error that function A cannot be found.
I'm unable to reproduce the exact app because it is proprietary, but I did create a dummy app that simulates the setup I have. I realize that there must be some difference between the dummy app and what I actually have, but I can't figure it out. The function in question is there, so I fundamentally don't understand why it's not being found.
library(shiny)
ui <- fluidPage(
sliderInput(inputId = "num",
label = "Choose a number",
value = 25, min = 1, max = 100),
actionButton(inputId = "action",
label = "Update"),
plotOutput("hist"),
verbatimTextOutput("stats")
)
server <- function(input, output) {
data <- eventReactive(input$action, {
input$num*2
})
data2 <- reactive({
data()*2
})
output$stats <- renderPrint({
data2()
})
}
shinyApp(ui = ui, server = server)

R Shiny DashboardPage search input

I have a UI that is projectdashboard in R shiny. I want to be able to type in a text/search box and have the data associated with it show up as i type.
server <- function(input, output,session) {
output$ui_names = renderUI({
name_list = mydata()[,"names"]
pickerInput("name", label=h3(" Names:"),
choices = sort(unique(name_list)),options = list("actions-box" = TRUE,"live-search" = TRUE,"none-selected-text"='Select Names'),
selected = NULL,multiple = TRUE)
})
ui <- dashboardPage(
dashboardHeader(title=textOutput("title"),titleWidth = 1500),
dashboardSidebar(
uiOutput("ui_names")
)
shinyApp(ui = ui, server = server)
This however does not give me expected or working results. How can i put a text/searchbar in the dashboard side bar, that will 'live-search' the data i am feeding it.
you can use the following:
sidebarSearchForm(textId = "searchText", buttonId = "searchButton",label = "Search...")
Please check if this meet your requirements

navigating to specific tab from external link shiny

I'm trying to give access to a specific view of my shiny dashboard to an external application. Basically, I want to give them a url link with a filter parameter so that when they click on the link, my shiny dashboard opens up on the specific view with the filters applied. I came across some other posts regarding the same on SO
Externally link to specific tabPanel in Shiny App
I tried using the code to figure out the solution, but haven't been able to. This is what I currently have, what I'd like to have is something like
http://127.0.0.1:7687/?url=%22Plot%202%22&species=%22setosa%22
This should open up the Plot 2 tab of the dashboard and apply the relevant filters. Any help on this would be great. Thanks!
library(shiny)
library(DT)
# Define UI for application that draws a histogram
ui <- navbarPage(title = "Navigate", id = 'nav',
# Application title
tabPanel("Plot",
plotOutput("distPlot")
),
tabPanel("Plot 2",
selectInput("species", "Select Species", choices = c("setosa", "virginica"),
multiple = T, selected = NULL),
dataTableOutput("tbl1")
)
)
# Define server logic required to draw a histogram
server <- function(input, output, session) {
observe({
query <- parseQueryString(session$clientData$url_search)
if(!is.null(query$url)) {
url <- strsplit(query$url,"/")[[1]]
updateTabsetPanel(session, 'nav', url)
}
})
output$distPlot <- renderPlot({
hist(rnorm(100), col = 'darkgray', border = 'white')
})
output$tbl1 <- renderDataTable({
tmp <- iris
if(!is.null(input$species))
tmp <- iris[which(iris$Species %in% input$species), ]
datatable(tmp)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Your observe should be the following:
observe({
query <- parseQueryString(session$clientData$url_search)
if(!is.null(query$url)) {
url <- strsplit(query$url,"\"")[[1]][2]
species <- strsplit(query$species, "\"")[[1]][2]
updateTabsetPanel(session, 'nav', url)
updateSelectInput(session, 'species',selected = species)
}
})

Shiny - populate static HTML table with filtered data based on input

I am currently working on a Shiny app which displays a static HTML table, sourced from another file, because of the size of the HTML code. The table is initialized with an empty data table in order to render the empty table. Above the HTML table are normal selectizeInput fields which filter a data table in the background (via a observe() function). The HTML table should then be populated with the filtered data table.
I am stuck at the process of updating the HTML table with the "new" data table. I tried sourcing the table again in the observe() - no change. I initialized the data table as reactiveValue and wrapped the HTML table with the reactive()-Function - again no change.
Here is a toy example which somewhat resembles my Shiny app:
app.R
library(shiny)
ui <- fluidPage(
fluidRow(
column(width = 6, uiOutput("cars"))
),
fluidRow(
column(width = 6, htmlOutput("html.table"))
)
)
server <- function(input, output) {
filtered_cars <- data.frame(matrix("NA", nrow = 1, ncol = 4, dimnames = list("NA", c("mpg","cyl","disp","hp"))))
source("server_html_table.R", local = TRUE)
output$cars <- renderUI({
selectizeInput(
inputId = "cars",
label = NULL,
choices = rownames(mtcars),
options = list(placeholder = 'Cars')
)
})
output$html.table <- renderUI({
html.table
})
observeEvent(input$cars, {
filtered_cars <- subset(mtcars, rownames(mtcars) %in% input$cars)
#some kind of update for the html table missing
})
}
# Run the application
shinyApp(ui = ui, server = server)
server_html_table.R
html.table <- tags$table(style = "border: 1px solid black; padding: 1%; width: 100%;",
tags$tr(
tags$th("Car Name"),
tags$th("MPG"),
tags$th("CYL"),
tags$th("DISP"),
tags$th("HP")
),
tags$tr(
tags$td(rownames(filtered_cars)),
tags$td(filtered_cars$mpg),
tags$td(filtered_cars$cyl),
tags$td(filtered_cars$disp),
tags$td(filtered_cars$hp)
)
)
As you can see, the table cells do not update. I am aware that there is some kind of update function missing in the observeEvent (like updateSelectizeInput()), but I cannot figure out a way to code it on my own.
I am grateful for any form of ideas or tips!
EDIT #1: Maybe to make the point about the HTML table clearer - I am displaying a Profit and Loss table in my app which needs to be build manually via HTML. Hence, I cannot use the usual dataTableOutput() and renderDataTable() functions. As the table relies heavily on CSS, the usage of basic HTML is much easier than the htmlTable package.
I found a solution to my problem!
The static html table is wraped in a function, which will be sourced once on startup in the server part of the app and then called in the renderUI() function. The render-function will be triggered every time a user changes the menu. Here I filter the dataframe regarding to the input and pass it to the "build_table" function. Each cell of the table is then populated with the needed values from the dataframe via indexes. The function return the full html table back to the renderUI().
This is the toy example from above, adjusted to the working solution:
app.R
library(shiny)
ui <- fluidPage(
fluidRow(
column(width = 6, uiOutput("cars"))
),
fluidRow(
column(width = 6, htmlOutput("html.table"))
)
)
server <- function(input, output) {
source("server_html_table.R", local = TRUE)
output$cars <- renderUI({
selectizeInput(
inputId = "cars",
label = NULL,
choices = rownames(mtcars),
options = list(placeholder = 'Cars')
)
})
output$html.table <- renderUI({
input$cars
isolate({
filtered_cars <- subset(mtcars, rownames(mtcars) %in% input$cars)
build_table(filtered_cars)
})
})
}
# Run the application
shinyApp(ui = ui, server = server)
server_html_table.R
build_table <- function(data){
html.table <- tags$table(style = "border: 1px solid black; padding: 1%; width: 100%;",
tags$tr(
tags$th("Car Name"),
tags$th("MPG"),
tags$th("CYL"),
tags$th("DISP"),
tags$th("HP")
),
tags$tr(
tags$td(rownames(data)),
tags$td(data$mpg),
tags$td(data$cyl),
tags$td(data$disp),
tags$td(data$hp)
)
)
return(html.table)
}

Resources