Access a dynamically generated input in r shiny
This solution mimics a couple others found on SO, namely this one.
The key is to create a reactiveValues
object and then assign the values using [[i]]
. In my case it helped to use a submit button to trigger that.
Complete, working code is as follows:
UI module:
library(shiny)
mod1UI <- function(id) {
ns <- NS(id)
tagList(
numericInput(ns("n"), "N",value = NULL),
actionButton(ns("draw"),"Generate Letters"),
hr(),
numericInput(ns("groups"), "Enter number of groups (1-3)", value=NULL),
uiOutput(ns("groupings")),
actionButton(ns("submit"), "Submit Groupings")
)
}
Server Module:
mod1 <- function(input, output, session, data) {
ns <- session$ns
x <- reactiveValues(data=NULL)
observeEvent(input$draw, {
req(input$n)
x$data <- sample(letters,input$n)
})
output$groupings <- renderUI({
req(input$groups)
ltrs <- data()
lapply(1:input$groups, function(i) {
selectizeInput(paste0(session$ns("usergroup"),i),
paste0("Select letters for Group ", i),
choices = ltrs,
options = list(placeholder = "Select letters for this group",
onInitialize = I('function() { this.setValue(""); }')), multiple=T)
})
})
gps <- reactiveValues(x=NULL)
observeEvent(input$submit, {
lapply(1:input$groups, function(i) {
gps$x[[i]] <- input[[paste0("usergroup", i)]]
})
})
test <- session$ns("test")
return(list(dat = reactive({x$data}),
groups = reactive({gps$x})
))
}
UI:
ui <- navbarPage("Fancy Title",id = "tabs",
tabPanel("Panel1",
sidebarPanel(
mod1UI("input1")
),
mainPanel(verbatimTextOutput("lettersy")
)
)
)
Server:
server <- function(input, output, session) {
y <- callModule(mod1, "input1", data=y$dat)
output$lettersy <- renderText({
as.character(c(y$groups()))
})
}
shinyApp(ui, server)
Return input as list in reactive shiny - dynamic UI in insert UI
Try this:
output$out <- renderPrint({
invisible(lapply(handler(), function(handle) {
cat(paste0(paste0(handle(), collapse = " "), "\n"))
}))
})
handle()
returns a list, the first call to paste0
creates one string, the second paste0
adds a new line so that all values from one module are on the same line. invisible
prevents that the return value from lapply
gets printed (only the sideeffect from cat
is printed)
Dynamically add columns to dataframe using Shiny input
Perhaps you are looking for this
library(shiny)
library(tidyr)
library(dplyr)
ui <- shinyUI(fluidPage(
sidebarPanel(
actionButton("add_btn", "Add Textbox"),
actionButton("rm_btn", "Remove Textbox"),
textOutput("counter")
),
mainPanel(uiOutput("textbox_ui")
,tableOutput("table")
)
))
server <- shinyServer(function(input, output, session) {
# Track the number of input boxes to render
counter <- reactiveValues(n = 0, df=NULL)
# Track all user inputs
AllInputs <- reactive({
x <- reactiveValuesToList(input)
})
observeEvent(input$add_btn, {
counter$n <- counter$n + 1
})
observeEvent(input$rm_btn, {
if (counter$n > 0) counter$n <- counter$n - 1
})
output$counter <- renderPrint(print(counter$n))
textboxes <- reactive({
n <- counter$n
if (n > 0) {
isolate({
lapply(seq_len(n), function(i) {
textInput(inputId = paste0("textin", i),
label = paste0("Textbox", i),
value = AllInputs()[[paste0("textin", i)]])
})
})
}
})
output$textbox_ui <- renderUI({ textboxes() })
df1 <- data.frame()
observe({
n <- counter$n
if (n > 0) {
df1 <- data.frame()
lapply(1:n, function(i){
req(input[[paste0("textin", i)]])
df1 <<- rbind(df1,data.frame(input[[paste0("textin", i)]]))
})
}
counter$df <- df1
})
output$table <- renderTable({
if (is.null(counter$df)) return(NULL)
else {
n <- nrow(counter$df)
if (n>0) {
colnames(counter$df) <- "values"
df1 <- counter$df %>% mutate(row=row_number())
df1 %>% pivot_wider(names_prefix="Textbox", names_from = row, values_from = values)
}else return(NULL)
}
})
})
shinyApp(ui, server)
R shiny use dynamic UI's input to multiply by group summed values
Update below two reactive objects, and it should work.
Change the textInput to numericInput
output$modality <- renderUI({
map(modality_names(), ~ numericInput(.x, label = paste(.x," minutes"),
value = isolate(input[[.x]])))
})
Assuming we are starting from 3rd column and there are 3 urgencies for each modality, subset every 3 columns and rowSums
, then do matrix multiplication using %*%
by input modalities which we are getting using sapply
loop
output$template = renderReactable({
res <- df2()
res$Total_minutes <- sapply(seq(3, ncol(res), 3), function(i){
rowSums(res[, i + 0:2])
}) %*% sapply(modality_names(), function(i){ input[[ i ]] })
reactable(res)
})
Related Topics
Split/Subset a Data Frame by Factors in One Column
Knitr: How to Prevent Text Wrapping in Output
Control the Height in Fluidrow in R Shiny
How to Install a Package from a Download Zip File
How to Delete Rows from a Data.Frame, Based on an External List, Using R
Emoticons in Twitter Sentiment Analysis in R
Improve Centering County Names Ggplot & Maps
Generate Correlated Random Numbers from Binomial Distributions
How 'Poly()' Generates Orthogonal Polynomials? How to Understand the "Coefs" Returned
How to Add a Factor Column to Dataframe Based on a Conditional Statement from Another Column
R - When Trying to Install Package: Internetopenurl Failed
Rcpp Function Check If Missing Value
Rstudio Shiny List from Checking Rows in Datatables
R: How to Run Some Code on Load of Package
Sparse Matrix to a Data Frame in R
Overlay Two Ggplot2 Stat_Density2D Plots with Alpha Channels
Removing One Tablegrob When Applied to a Box Plot with a Facet_Wrap