R Shiny Dynamic Input

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)
})

Sample Image



Related Topics



Leave a reply



Submit