Can someone show me how to get the tabName of the selected argonTab in an argonTabSet please, in a shiny app. I need it for downstream data subsetting.
The example below follows, somewhat, my actual app, where I call argonTabSet with do.call. The tabnames in my real app can vary so I am looking for something without hard coding them. The app is modularised, though I can’t get any values to return with input$t_brnd if I also wrap the argonTabSet id in ns().
library(shiny)
library(argonR)
library(argonDash)
mod_price_ov_UI <- function(id) {
ns <- NS(id)
tagList(
uiOutput(ns('ot_cat_brnd_rtlr'))
, uiOutput(ns('selected_tab'))
)
}
mod_price_ov <- function(id){
moduleServer(id,function(input, output, session) {
output$ot_cat_brnd_rtlr <- renderUI({
ns <- session$ns
brands <- paste0('brand_', 1:4)
tagList(
do.call(argonTabSet, c(
# id = ns('t_brnd'),
id ='t_brnd',
lapply(1:length(brands), function(i) {
argonTab(
tabName = brands[i],
active = ifelse(i == 1, T, F)
)
})
))
)
})
output$selected_tab <- renderUI({
input$t_brnd
})
})
}
shiny::shinyApp(
ui = argonDashPage(
body = argonDashBody(mod_price_ov_UI('ov'))
),
server = function(input, output, session) {
mod_price_ov('ov')
}
)
UPDATE
A comment (which seems to have been deleted) asked for an example closer to the actual use case, which I present below. I may need to revise the question title as the example now illustrates my actual issue. I thought that getting the tabname would ultimately help me get to this point.
The table category_tally starts with an overall summary total. I require to provide some functionality (with a radiobutton ‘Brand Stats ’ for example) where the user can update the total filtered by the brand in the selected tabname (also reflected in the selected datatable) , and back again, if the button equals ‘NO’.
I can only seem to get the button to work on the last tab, not the first 3.
library(shiny)
library(argonR)
library(argonDash)
library(magrittr)
library(tidyverse)
library(DT)
set.seed(1234)
mod_price_ov_UI <- function(id) {
ns <- NS(id)
tagList(
tableOutput(ns('category_tally')),
uiOutput(ns('ot_cat_brnd_rtlr')))
}
mod_price_ov <- function(id){
moduleServer(
id,
function(input, output, session) {
toy_rtcv <- reactive({tibble(
category = sample(paste0('cat_' , 1:3), 100, replace = T)
, brand = sample(paste0('brand_', 1:4), 100, replace = T)
)})
output$category_tally <- renderTable({toy_rtcv() %>% summarise(total = n())})
output$ot_cat_brnd_rtlr <- renderUI({
ns <- session$ns
brands <- toy_rtcv() %>% select(brand) %>% distinct() %>% pull(brand)
tagList(
do.call(argonTabSet, c(id= 't_brnd', lapply(1:length(brands), function(i) {
argonTab(
tabName = brands[i]
, active = ifelse(i == 1, T, F)
, radioButtons(ns(paste0('rdio_cat_brnd_rtlr', brands[i]))
, 'Brand Stats'
, choices = c('YES', 'NO')
, selected = 'NO'
, inline = T
)
, dataTableOutput(ns(paste0('ot_retailer_', brands[i])))
)}))))})
observe({
brands <- toy_rtcv() %>% select(brand) %>% distinct() %>% pull(brand)
lapply(1:length(brands), function(i) {
output[[paste0('ot_retailer_', brands[i])]] = renderDataTable({
toy_rtcv() %>%
filter(brand == brands[i])
})})})
observe({
brands <- toy_rtcv() %>% select(brand) %>% distinct() %>% pull(brand)
lapply(1:length(brands), function(i){
if(is.null(input[[paste0('rdio_cat_brnd_rtlr', brands[i])]]))
return(NULL)
if(input[[paste0('rdio_cat_brnd_rtlr', brands[i])]] == 'YES'){
output$category_tally <- renderTable({
toy_rtcv() %>%
filter(brand == brands[i]) %>%
summarise(total = n())})
} else {
output$category_tally <- renderTable({
toy_rtcv() %>%
summarise(total = n())
})}})})})
}
shiny::shinyApp(
ui = argonDashPage(
body = argonDashBody(mod_price_ov_UI('ov'))
),
server = function(input, output, session) {mod_price_ov('ov')}
)
Related
I have just started include bookmark functionality to my app. My app have a few selection inputs which do not seem to be restored and I couldnt figure out the problems.
The app has 2 key inputs:
The radio button on the sidebar
The date/number ranges
At the current state, the app cant seem to restore the radio button (if I switch to duration, it just doesnt work)
The simplify code is below:
library(shiny)
library(data.table)
library(tidyverse)
library(lubridate)
library(shinydashboard)
library(zoo)
library(shinyWidgets)
library(nycflights13)
flight.dt <- flights %>% mutate(flight.date =ymd(substr(time_hour,1,10)),duration=round(air_time,-2))
### --------Analyse module ---------------------------
plotUI <- function(id) {
ns <- NS(id)
tagList(
uiOutput(ns("groupmenu")),
plotOutput(ns("plot"))
)
}
plotServer <- function(id,method,carr) {
moduleServer(
id,
function(input, output, session) {
filtered.data <- reactive(flight.dt %>% filter(carrier == carr))
output$groupmenu <- renderUI({
getselection <- if (method() != "duration") c("Year Quarter"="yearqtr") else c("Duration"="dur.grp")
rng.min <- switch (method(),
"date" = min(filtered.data()$flight.date),
"duration" = max(0,min(filtered.data()$duration,na.rm = TRUE)))
rng.max <- switch(method(),
"date" = max(filtered.data()$flight.date),
"duration" = max(0,max(filtered.data()$duration,na.rm = TRUE)))
ns <- session$ns
tagList(
fluidRow(
column(2,selectInput(ns("group"), "Group by:",choices =as.list(getselection))),
conditionalPanel("input.method == 'date'",
dateRangeInput(ns("daterange"),"Date range:",start = rng.min,end = rng.max,format = "dd/mm/yyyy", separator = " - ")),
conditionalPanel("input.method == 'duration'",
numericRangeInput(ns("durrange"), label = "Duration range:",value = c(rng.min,rng.max)))
)
)
})
dt <- reactiveVal(NULL)
observeEvent(input$group,{
tmp <- filtered.data() %>% mutate(sel.method = switch(method(),"date" = flight.date,"duration" = duration))
if (input$group == "yearqtr") {
tmp$key <- paste0(year(tmp$sel.method),"-Q",quarter(tmp$sel.method))
} else if (input$group == "dur.grp") {
tmp$key <- tmp$duration
}
dt(tmp)
})
dt.sum <- reactive({
req(dt())
setDT(dt())
if (method() == "date") {
tmp <- dt()[sel.method >= input$daterange[1] & sel.method <= input$daterange[2]]
} else if (method() == "duration") {
tmp <- dt()[key >= input$durrange[1] & key <= input$durrange[2]]
}
tmp %>% group_by(key) %>% dplyr::summarise(count=n())
})
output$plot <- renderPlot({
dt.sum() %>% ggplot(aes(x = as.character(key), y = count)) + geom_col()
})
}
)
}
### UI part -----------------------
header <- dashboardHeader(title = 'Analysis')
sidebar <- dashboardSidebar(
radioButtons("method", "Select method:",c("Date" = "date","Duration" = "duration"),selected = "date"),
bookmarkButton()
)
body <- dashboardBody(uiOutput('tablist'))
ui <- function(request) {
dashboardPage(title="Analysis", header,sidebar,body)
}
### Server part ----------------------------
server = function(input, output) {
method <- reactive(input$method)
carr <- reactive(unique(flight.dt$carrier)[1:3])
ntabs <- reactive(length(carr()))
observeEvent(ntabs(),{
lapply(1:ntabs(), function (i) plotServer(paste0("count",i),method,carr()[i]))
})
output$tablist = renderUI({
addtabs <- lapply(1:ntabs(),function (i) {
tabPanel(carr()[i],plotUI(paste0("count",i)))
})
do.call(tabsetPanel, addtabs)
})
}
### Running part ----------------------------
enableBookmarking("server")
shinyApp(ui, server)
Put your ui elements you want restored within ui function. See simplified example:
library(shiny)
library(shinydashboard)
### UI part -----------------------
ui <- function(request) {
header <- dashboardHeader(title = 'Analysis')
sidebar <- dashboardSidebar(
radioButtons("method", "Select method:",c("Date" = "date","Duration" = "duration"),selected = "date"),
bookmarkButton()
)
body <- dashboardBody("BODY")
dashboardPage(title="Analysis", header,sidebar,body)
}
### Server part ----------------------------
server = function(input, output) {
}
### Running part ----------------------------
enableBookmarking("server")
shinyApp(ui, server)
I show you my shiny application, but I have a problem, I cannot update the selectimput, I have used updateSelectInput but it does not work.
I have two selectInputs inside a tabsetPanel, since I need to update the table with two filters, one is the category and the other the subcategory.
here my code.
library(shiny)
library(tidyverse)
library(DT)
cat1<-rep("LINEA BLANCA", 75)
cat2<- rep("VIDEO", 75)
subcat1<-rep("LAVADORAS", 40)
subcat2<- rep("REFRIS", 35)
subcat3<- rep("TV", 40)
subcat4<- rep("SONIDO", 35)
vent<-sample(100:900, 150, replace=T)
segm1<-rep("AAA", 25)
segm2<-rep("BBB", 25)
segm3<-rep("CCC", 25)
segm4<-rep("ABB", 25)
segm5<-rep("ACC", 25)
segm6<-rep("BAC", 25)
db<- tibble(segment=c(segm1,segm2,segm3,segm4,segm5,
segm1),CATEGORIA=c(cat1,cat2), SUBCAT=c(subcat1,subcat2, subcat3, subcat4), vent=vent)
ui <- fluidPage(
# App title
titlePanel("EXAMPLE"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Tabset w/ plot, summary, and table ----
tabsetPanel(type = "tabs",
tabPanel("Ana_inv", uiOutput("selectcat"), uiOutput("selectsubcat"),DT::dataTableOutput("ana_inv")),
#tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Table", tableOutput("table"))
)
)
)
)
server <- function(input, output, session) {
output$selectcat <- renderUI({
selectInput("Cat", "Seleccione Categoria", choices = c("ALL",as.vector(db$CATEGORIA)))
})
output$selectsubcat <- renderUI({
#opciones<- db_prueba %>% filter(CATEGORIA==input$CAT)
selectInput("Subcat", "Seleccione Subcategoria", choices = c("ALL",as.vector(db$SUBCAT)))
})
activar<- reactive({
req(input$Cat)
req(input$Subcat)
opciones<- db %>% filter(CATEGORIA==input$Cat)
if(input$Cat == "TODOS") {
filt1 <- quote(CATEGORIA != "#?><")
} else {
filt1 <- quote(CATEGORIA == input$Cat)
}
if (input$Subcat == "TODOS") {
filt2 <- quote(SUBCAT != "#?><")
} else {
filt2 <- quote(SUBCAT == input$Subcat)
}
db %>%
filter_(filt1) %>%
filter_(filt2) %>% group_by(segment)%>%
summarise(SKUs=n(),
vta=sum(vent))
})
# Return the formula text for printing as a caption ----
output$ana_inv <- DT::renderDataTable({
activar()
})
}
shinyApp(ui = ui, server = server)
So I need that if the category "LINEA BLANCA" is selected in the subcategory it only shows "REFRIS" and "LAVADORAS", but also if someone selects "ALL" in the category he can also select each subcategory, that is, it can be filtered by subcategory assuming I only want to see subcategories.
I have tried many ways but none works, any ideas? you can run the application in R to get an idea of what I want.
Try this
server <- function(input, output, session) {
output$selectcat <- renderUI({
selectInput("Cat", "Seleccione Categoria", choices = c("ALL",as.vector(db$CATEGORIA)))
})
output$selectsubcat <- renderUI({
req(input$Cat)
if (input$Cat=="ALL"){ df <- db
}else df <- db %>% filter(CATEGORIA %in% input$Cat)
selectInput("Subcat", "Seleccione Subcategoria", choices = c("ALL",as.vector(df$SUBCAT)))
})
activar<- reactive({
req(input$Cat,input$Subcat)
if (input$Cat=="ALL"){ df <- db
}else df <- db %>% filter(CATEGORIA %in% input$Cat)
if (input$Subcat=="ALL"){ df <- df
}else df <- df %>% filter(SUBCAT == input$Subcat)
df %>%
group_by(segment) %>%
summarise(SKUs=n(),
vta=sum(vent))
})
# Return the formula text for printing as a caption ----
output$ana_inv <- DT::renderDataTable({
activar()
})
}
I set up a filter by year using year_filter and would like the default view to be 2021. How to do I this given the code below? Currently, the default display is to show all data entries for all years.
The complete code and file can be found here for reference: https://drive.google.com/drive/folders/1C7SWkl8zyGXLGEQIiBEg4UsNQ5GDaKoa?usp=sharing
Thank you for your assistance!
# Define UI for application
ui <- fluidPage(
tags$div(
style = "padding: 10px;",
# Application title
titlePanel("Testing and Quarantine Measures"),
fluidRow(
uiOutput("CountryFilter_ui"),
uiOutput("YearFilter_ui")
),
fluidRow(
tags$div(style = "width: 100%; overflow: scroll; font-size:80%;",
DT::dataTableOutput('travel_table')
)
)
)
)
server <- function(input, output) {
# Render UI
output$CountryFilter_ui <- renderUI({
countries <- travel_clean %>%
pull(country_area)
selectInput('country_filter', 'Member State Filter', choices = countries, multiple = TRUE)
})
output$YearFilter_ui <- renderUI({
year <- travel_clean %>%
pull(year)
selectInput('year_filter', 'Year Filter', choices = year, multiple = TRUE)
})
# Filter data
travel_filtered <- reactive({
tmp_travel <- travel_measures %>%
select(-Sources)
if(is.null(input$country_filter) == FALSE) {
tmp_travel <- tmp_travel %>%
filter(`Country/area` %in% input$country_filter)
}
return(tmp_travel)
})
travel_filtered <- reactive({
tmp_travel <- travel_measures %>%
select(-Sources)
if(is.null(input$year_filter) == FALSE) {
tmp_travel <- tmp_travel %>%
filter(`Year` %in% input$year_filter)
}
return(tmp_travel)
})
I have put together a Shiny app that reactively creates lists while simultaneously removing those selections from the list you're selecting from. I'm trying to put together a feature where you click a reset button and it does the following:
1.) Deselects all input options
2.) Sets the Age Range to 18 - 104 (so it captures all values)
3.) Moves the other two sliders to zero
I'm trying to use the shinyjs::reset function, but it doesn't appear to be working. Take a look:
df <- read.csv('https://raw.githubusercontent.com/gooponyagrinch/sample_data/master/datasheet.csv')
library(shiny)
library(shinyWidgets)
library(shinyjs)
library(tidyverse)
library(DT)
ui <- fluidPage(
div(id = "myapp",
fluidRow(
column("",
width = 10, offset = 1,
tags$h3("Select Area"),
panel(
sliderInput("current", "Current Score",
min = 0, max = 100, value = 20),
sliderInput("projected", "Projected Score",
min = 0, max = 100, value = 20),
sliderInput("age", "Age",
min = 18, max = max(df$age), value = c(18,24)),
checkboxGroupInput("ethnicity",label = "Ethnicity",
choices = list("Caucasian"="Caucasian",
"African-American"="African-American",
"Hispanic"="Hispanic",
"Other"="Other")),
checkboxInput('previous', label = "Previous Sale"),
checkboxInput('warm', label = "Warm Lead"),
actionButton("button", "Add to List"),
actionButton("reset", "Reset form")),
textOutput("counter"),
tags$h2("Data to filter"),
DT::dataTableOutput("table"),
tags$h2("IDs added to list"),
DT::dataTableOutput("addedToList")
)
)
)
)
server <- function(input, output, session) {
filterData = reactiveVal(df %>% mutate(key = 1:nrow(df)))
addedToList = reactiveVal(data.frame())
filtered_df <- reactive({
res <- filterData() %>% filter(current_grade >= input$current)
res <- res %>% filter(projected_grade >= input$projected)
res <- res %>% filter(age >= input$age[1] & age <= input$age[2])
res <- res %>% filter(ethnicity %in% input$ethnicity | is.null(input$ethnicity))
if(input$previous == TRUE)
res <- res %>% filter(previous_sale == 1)
if(input$warm == TRUE)
res <- res %>% filter(warm_lead == 1)
res
})
output$counter <- renderText({
res <- filtered_df() %>% select(customer_id) %>% n_distinct()
res
})
output$table <- renderDataTable({
res <- filtered_df() %>% distinct(customer_id)
res
})
observeEvent(input$button, {
addedToList(rbind(addedToList(),
filterData() %>% filter(key %in% filtered_df()$key) %>%
select(customer_id) %>% distinct() ))
filterData(filterData() %>% filter(!key %in% filtered_df()$key))
})
observeEvent(input$reset, {
shinyjs::reset("myapp")
})
output$addedToList <- renderDataTable({
addedToList()
})
}
shinyApp(ui,server)
Am I missing something?
All you need to do is ensure that your application is listening for a call to "ShinyJS" in your application. In the UI, add the useShinyJS() call!
ui <- fluidPage(
useShinyJS()
div(id = "myapp",
fluidRow(...)
)
I also should note this looks like a repeat of this question. 'Reset inputs' button in shiny app
I am trying to get input choices dependent on previous input.
require(shiny)
require(dplyr)
dat <- data.frame(id1 = c(rep("A",5),rep("B",5)),
id2 = c(rep("C",3),rep("D",3),rep("E",4)),
id3 = c(rep("F",2),rep("G",3),rep("H",5)), stringsAsFactors=FALSE)
ui <- shinyUI(fluidPage(
sidebarPanel(
selectInput('id1', 'ID1', choices = unique(dat$id1)),
selectInput("id2", "ID2", choices = unique(dat$id2)),
selectInput("id3", "ID3", choices = unique(dat$id3))
)
)
)
server <- function(input, output,session) {
observeEvent(
{
input$id1
},{
input$id2
temp <- dat %>% filter(id1%in%input$id1)
updateSelectInput(session,"id2",choices = unique(temp$id2))
}
)
}
shinyApp(ui = ui, server = server)
This works for Input 1 and 2, however if i add another Input to observeEvent, the app chrashes. E.g:
server <- function(input, output,session) {
observeEvent(
{
input$id1
},{
input$id2
temp <- dat %>% filter(id1%in%input$id1)
updateSelectInput(session,"id2",choices = unique(temp$id2))
},{
input$id3
temp <- dat %>% filter(id1%in%input$id1 & id2%in%input$id2)
updateSelectInput(session,"id3",choices = unique(temp$id3))
}
)
}
How can I pass further Inputs to observeEvent ?
Update: I found a solution for the problem. I wrapped the Inputs in a reactive function, split the Output and passed it to the corresponding observeEvent functions.
server <- function(input, output,session) {
change <- reactive({
unlist(strsplit(paste(c(input$id1,input$id2,input$id3),collapse="|"),"|",fixed=TRUE))
})
observeEvent(input$id1,{
temp <- dat %>% filter(id1 %in% change()[1])
updateSelectInput(session,"id2",choices = unique(temp$id2))
}
)
observeEvent(input$id2,{
temp <- dat %>% filter(id1 %in% change()[1] & id2 %in% change()[2])
updateSelectInput(session,"id3",choices = unique(temp$id3))
}
)
}