Nesting observeEvent within observeEvent in R Shiny
In R Shiny, I have been able to realize the function of freely inserting input fields with an actionButton, using this technique: R Shiny: How to create an "Add Field" Button (call it Section A). Now within Section A, I want to add another section that allows users to freely insert fields with another actionButton (Section B). So Section B is within Section A.
Using the technique quoted above, it looks like I need to nest an observeEvent({}) within an observeEvent({}), but when I did so, I got this error: Error in as.vector: cannot coerce type 'environment' to vector of type 'character'.
Anyone has got any ideas how to get around? Here is the relevant code:
server part:
################################# Additional Tables ############################
### UI part
ids <<- NULL
idsR <- reactiveValues(v=c())
idsa <<- NULL
idsaR <- reactiveValues(v=c())
observeEvent(input$addTable,{
if (is.null(ids)){
ids <<- 1
idsR$v <- c()
}else{
ids <<- c(ids, max(ids)+1)
}
idsR$v <- ids
output$additionalTables <- renderUI({
lapply(1:length(ids),function(i){
## Input: Joining condition 1 for the first table
output[[paste0("joinCondition_1_a_additional",ids[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_a_additional",ids[i]), HTML("Column to Join (1st Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input$table) & condition1(), 2]))))
})
## Input: Joining condition 1 for the additional table
output[[paste0("joinCondition_1_b_additional",ids[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_b_additional",ids[i]), HTML("Column to Join (Additional Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2]))))
})
## Input: Tables in the first table's schema
output[[paste0("additional_table",ids[i])]] <- renderUI({
selectInput(paste0("additional_table",ids[i]), HTML("Table <font size = '3' color = 'red'>*</font>"), choices = as.list(sort(unique(allTableNames[allTableNames[,1] == trimws(input$schema), 2]))))
})
## Input: Columns in the additional table
output[[paste0("additional_column",ids[i])]] <- renderUI({
selectInput(paste0("additional_column",ids[i]), HTML("Non-aggregate columns <font size = '3' color = 'red'>*</font>"), multiple = TRUE, choices = as.list(c(
####Bill suggested not allowing users to select all columns #"*",
sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2 ])))))
})
tagList(
tags$hr(style="height:1px;border:none;background-color:#D1D1D1;" ),
tags$h4(sprintf("Additional Table #%d",ids[i]),align = "center", style="color:#2955A0;font-weight:bold; font-family:times;"),
fluidRow(
column(
# Input: joining method
radioButtons(inputId = paste0("joiningMethod",ids[i]), label = HTML("Method <font size = '3' color = 'red'>*</font>"), choices = c("left", "inner")), width = 4),
column(
# Input: the origin of the additional table
radioButtons(inputId = paste0("tableOrigin",ids[i]), label = HTML("Is the additional table in CCW or external? <font size = '3' color = 'red'>*</font>"), choices = c("CCW", "external")), width = 8)),
# If CCW
conditionalPanel(
condition = paste0("input.",paste0("tableOrigin",ids[i]),"== 'CCW'"),
# Input: table for the additional table
uiOutput(outputId = paste0("additional_table",ids[i])),
# Input: columns for the additional table
uiOutput(outputId = paste0("additional_column",ids[i])),
tags$h4("Joining Condition",align = "center", style="color:#2955A0;font-weight:bold; font-family:times;"),
fluidRow(
column(
# Input: joining condition for the first table
uiOutput(outputId = paste0("joinCondition_1_a_additional",ids[i])), width = 6),
column(
# Input: joining condition for the additional table
uiOutput(outputId = paste0("joinCondition_1_b_additional",ids[i])), width = 6)
),
uiOutput(outputId = paste0("additionaljoinCondition_additionalTable",ids[i])),
fluidRow(
column(12, align="center", offset = 0, actionButton(inputId = paste0("addjoiningCondition_additionalTable", ids[i]),"Add Another Joining Condition?", style="color: #fff; text-align: center; background-color: #337ab7; border-color: #2e6da4"))
)
),
# If External
conditionalPanel(
condition = paste0("input.",paste0("tableOrigin",ids[i]),"== 'external'"),
# file upload UI for the additional table
fileInput(inputId = paste0("additionalTable",ids[i]), label = "Table to join with (csv file, with header in the first row)", accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv"))
)
)
## Additional Joining conditions for Additional Tables ##
observeEvent(input[[paste0("addjoiningCondition_additionalTable", ids[i])]],{
if (is.null(idsa)){
idsa <<- 1
idsaR$v <- c()
}else{
idsa <<- c(idsa, max(idsa)+1)
}
idsaR$v <- idsa
output[[paste0("additionaljoinCondition_additionalTable", ids[i])]] <- renderUI({
lapply(1:length(idsa),function(i){
## Input: Joining condition 1 for the first table
output[[paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i]), HTML("Column to Join (1st Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input$table) & condition1(), 2]))))
})
## Input: Joining condition 1 for the additional table
output[[paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i]), HTML("Column to Join (Additional Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2]))))
})
tagList(
fluidRow(
column(
# Input: joining condition for the first table --> Input: "output$joinCondition_1_a"
uiOutput(outputId = paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i])), width = 6),
column(
# Input: joining condition for the second table --> Input: "output$joinCondition_1_b"
uiOutput(outputId = paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i])), width = 6)
)
)
})
})
})
})
})
})
Since I used uiOutput to display the objects, a lot of the inputs were moved to server.R as wrapped in renderUI({}). The relevant ui part of the code only has the following:
uiOutput("additionaljoinCondition"),
fluidRow(
column(12, align="center", offset = 0, actionButton("addjoiningCondition","Add Another Joining Condition?", style="color: #fff; text-align: center; background-color: #337ab7; border-color: #2e6da4")))
),
r shiny
add a comment |
In R Shiny, I have been able to realize the function of freely inserting input fields with an actionButton, using this technique: R Shiny: How to create an "Add Field" Button (call it Section A). Now within Section A, I want to add another section that allows users to freely insert fields with another actionButton (Section B). So Section B is within Section A.
Using the technique quoted above, it looks like I need to nest an observeEvent({}) within an observeEvent({}), but when I did so, I got this error: Error in as.vector: cannot coerce type 'environment' to vector of type 'character'.
Anyone has got any ideas how to get around? Here is the relevant code:
server part:
################################# Additional Tables ############################
### UI part
ids <<- NULL
idsR <- reactiveValues(v=c())
idsa <<- NULL
idsaR <- reactiveValues(v=c())
observeEvent(input$addTable,{
if (is.null(ids)){
ids <<- 1
idsR$v <- c()
}else{
ids <<- c(ids, max(ids)+1)
}
idsR$v <- ids
output$additionalTables <- renderUI({
lapply(1:length(ids),function(i){
## Input: Joining condition 1 for the first table
output[[paste0("joinCondition_1_a_additional",ids[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_a_additional",ids[i]), HTML("Column to Join (1st Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input$table) & condition1(), 2]))))
})
## Input: Joining condition 1 for the additional table
output[[paste0("joinCondition_1_b_additional",ids[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_b_additional",ids[i]), HTML("Column to Join (Additional Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2]))))
})
## Input: Tables in the first table's schema
output[[paste0("additional_table",ids[i])]] <- renderUI({
selectInput(paste0("additional_table",ids[i]), HTML("Table <font size = '3' color = 'red'>*</font>"), choices = as.list(sort(unique(allTableNames[allTableNames[,1] == trimws(input$schema), 2]))))
})
## Input: Columns in the additional table
output[[paste0("additional_column",ids[i])]] <- renderUI({
selectInput(paste0("additional_column",ids[i]), HTML("Non-aggregate columns <font size = '3' color = 'red'>*</font>"), multiple = TRUE, choices = as.list(c(
####Bill suggested not allowing users to select all columns #"*",
sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2 ])))))
})
tagList(
tags$hr(style="height:1px;border:none;background-color:#D1D1D1;" ),
tags$h4(sprintf("Additional Table #%d",ids[i]),align = "center", style="color:#2955A0;font-weight:bold; font-family:times;"),
fluidRow(
column(
# Input: joining method
radioButtons(inputId = paste0("joiningMethod",ids[i]), label = HTML("Method <font size = '3' color = 'red'>*</font>"), choices = c("left", "inner")), width = 4),
column(
# Input: the origin of the additional table
radioButtons(inputId = paste0("tableOrigin",ids[i]), label = HTML("Is the additional table in CCW or external? <font size = '3' color = 'red'>*</font>"), choices = c("CCW", "external")), width = 8)),
# If CCW
conditionalPanel(
condition = paste0("input.",paste0("tableOrigin",ids[i]),"== 'CCW'"),
# Input: table for the additional table
uiOutput(outputId = paste0("additional_table",ids[i])),
# Input: columns for the additional table
uiOutput(outputId = paste0("additional_column",ids[i])),
tags$h4("Joining Condition",align = "center", style="color:#2955A0;font-weight:bold; font-family:times;"),
fluidRow(
column(
# Input: joining condition for the first table
uiOutput(outputId = paste0("joinCondition_1_a_additional",ids[i])), width = 6),
column(
# Input: joining condition for the additional table
uiOutput(outputId = paste0("joinCondition_1_b_additional",ids[i])), width = 6)
),
uiOutput(outputId = paste0("additionaljoinCondition_additionalTable",ids[i])),
fluidRow(
column(12, align="center", offset = 0, actionButton(inputId = paste0("addjoiningCondition_additionalTable", ids[i]),"Add Another Joining Condition?", style="color: #fff; text-align: center; background-color: #337ab7; border-color: #2e6da4"))
)
),
# If External
conditionalPanel(
condition = paste0("input.",paste0("tableOrigin",ids[i]),"== 'external'"),
# file upload UI for the additional table
fileInput(inputId = paste0("additionalTable",ids[i]), label = "Table to join with (csv file, with header in the first row)", accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv"))
)
)
## Additional Joining conditions for Additional Tables ##
observeEvent(input[[paste0("addjoiningCondition_additionalTable", ids[i])]],{
if (is.null(idsa)){
idsa <<- 1
idsaR$v <- c()
}else{
idsa <<- c(idsa, max(idsa)+1)
}
idsaR$v <- idsa
output[[paste0("additionaljoinCondition_additionalTable", ids[i])]] <- renderUI({
lapply(1:length(idsa),function(i){
## Input: Joining condition 1 for the first table
output[[paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i]), HTML("Column to Join (1st Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input$table) & condition1(), 2]))))
})
## Input: Joining condition 1 for the additional table
output[[paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i]), HTML("Column to Join (Additional Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2]))))
})
tagList(
fluidRow(
column(
# Input: joining condition for the first table --> Input: "output$joinCondition_1_a"
uiOutput(outputId = paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i])), width = 6),
column(
# Input: joining condition for the second table --> Input: "output$joinCondition_1_b"
uiOutput(outputId = paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i])), width = 6)
)
)
})
})
})
})
})
})
Since I used uiOutput to display the objects, a lot of the inputs were moved to server.R as wrapped in renderUI({}). The relevant ui part of the code only has the following:
uiOutput("additionaljoinCondition"),
fluidRow(
column(12, align="center", offset = 0, actionButton("addjoiningCondition","Add Another Joining Condition?", style="color: #fff; text-align: center; background-color: #337ab7; border-color: #2e6da4")))
),
r shiny
add a comment |
In R Shiny, I have been able to realize the function of freely inserting input fields with an actionButton, using this technique: R Shiny: How to create an "Add Field" Button (call it Section A). Now within Section A, I want to add another section that allows users to freely insert fields with another actionButton (Section B). So Section B is within Section A.
Using the technique quoted above, it looks like I need to nest an observeEvent({}) within an observeEvent({}), but when I did so, I got this error: Error in as.vector: cannot coerce type 'environment' to vector of type 'character'.
Anyone has got any ideas how to get around? Here is the relevant code:
server part:
################################# Additional Tables ############################
### UI part
ids <<- NULL
idsR <- reactiveValues(v=c())
idsa <<- NULL
idsaR <- reactiveValues(v=c())
observeEvent(input$addTable,{
if (is.null(ids)){
ids <<- 1
idsR$v <- c()
}else{
ids <<- c(ids, max(ids)+1)
}
idsR$v <- ids
output$additionalTables <- renderUI({
lapply(1:length(ids),function(i){
## Input: Joining condition 1 for the first table
output[[paste0("joinCondition_1_a_additional",ids[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_a_additional",ids[i]), HTML("Column to Join (1st Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input$table) & condition1(), 2]))))
})
## Input: Joining condition 1 for the additional table
output[[paste0("joinCondition_1_b_additional",ids[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_b_additional",ids[i]), HTML("Column to Join (Additional Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2]))))
})
## Input: Tables in the first table's schema
output[[paste0("additional_table",ids[i])]] <- renderUI({
selectInput(paste0("additional_table",ids[i]), HTML("Table <font size = '3' color = 'red'>*</font>"), choices = as.list(sort(unique(allTableNames[allTableNames[,1] == trimws(input$schema), 2]))))
})
## Input: Columns in the additional table
output[[paste0("additional_column",ids[i])]] <- renderUI({
selectInput(paste0("additional_column",ids[i]), HTML("Non-aggregate columns <font size = '3' color = 'red'>*</font>"), multiple = TRUE, choices = as.list(c(
####Bill suggested not allowing users to select all columns #"*",
sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2 ])))))
})
tagList(
tags$hr(style="height:1px;border:none;background-color:#D1D1D1;" ),
tags$h4(sprintf("Additional Table #%d",ids[i]),align = "center", style="color:#2955A0;font-weight:bold; font-family:times;"),
fluidRow(
column(
# Input: joining method
radioButtons(inputId = paste0("joiningMethod",ids[i]), label = HTML("Method <font size = '3' color = 'red'>*</font>"), choices = c("left", "inner")), width = 4),
column(
# Input: the origin of the additional table
radioButtons(inputId = paste0("tableOrigin",ids[i]), label = HTML("Is the additional table in CCW or external? <font size = '3' color = 'red'>*</font>"), choices = c("CCW", "external")), width = 8)),
# If CCW
conditionalPanel(
condition = paste0("input.",paste0("tableOrigin",ids[i]),"== 'CCW'"),
# Input: table for the additional table
uiOutput(outputId = paste0("additional_table",ids[i])),
# Input: columns for the additional table
uiOutput(outputId = paste0("additional_column",ids[i])),
tags$h4("Joining Condition",align = "center", style="color:#2955A0;font-weight:bold; font-family:times;"),
fluidRow(
column(
# Input: joining condition for the first table
uiOutput(outputId = paste0("joinCondition_1_a_additional",ids[i])), width = 6),
column(
# Input: joining condition for the additional table
uiOutput(outputId = paste0("joinCondition_1_b_additional",ids[i])), width = 6)
),
uiOutput(outputId = paste0("additionaljoinCondition_additionalTable",ids[i])),
fluidRow(
column(12, align="center", offset = 0, actionButton(inputId = paste0("addjoiningCondition_additionalTable", ids[i]),"Add Another Joining Condition?", style="color: #fff; text-align: center; background-color: #337ab7; border-color: #2e6da4"))
)
),
# If External
conditionalPanel(
condition = paste0("input.",paste0("tableOrigin",ids[i]),"== 'external'"),
# file upload UI for the additional table
fileInput(inputId = paste0("additionalTable",ids[i]), label = "Table to join with (csv file, with header in the first row)", accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv"))
)
)
## Additional Joining conditions for Additional Tables ##
observeEvent(input[[paste0("addjoiningCondition_additionalTable", ids[i])]],{
if (is.null(idsa)){
idsa <<- 1
idsaR$v <- c()
}else{
idsa <<- c(idsa, max(idsa)+1)
}
idsaR$v <- idsa
output[[paste0("additionaljoinCondition_additionalTable", ids[i])]] <- renderUI({
lapply(1:length(idsa),function(i){
## Input: Joining condition 1 for the first table
output[[paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i]), HTML("Column to Join (1st Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input$table) & condition1(), 2]))))
})
## Input: Joining condition 1 for the additional table
output[[paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i]), HTML("Column to Join (Additional Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2]))))
})
tagList(
fluidRow(
column(
# Input: joining condition for the first table --> Input: "output$joinCondition_1_a"
uiOutput(outputId = paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i])), width = 6),
column(
# Input: joining condition for the second table --> Input: "output$joinCondition_1_b"
uiOutput(outputId = paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i])), width = 6)
)
)
})
})
})
})
})
})
Since I used uiOutput to display the objects, a lot of the inputs were moved to server.R as wrapped in renderUI({}). The relevant ui part of the code only has the following:
uiOutput("additionaljoinCondition"),
fluidRow(
column(12, align="center", offset = 0, actionButton("addjoiningCondition","Add Another Joining Condition?", style="color: #fff; text-align: center; background-color: #337ab7; border-color: #2e6da4")))
),
r shiny
In R Shiny, I have been able to realize the function of freely inserting input fields with an actionButton, using this technique: R Shiny: How to create an "Add Field" Button (call it Section A). Now within Section A, I want to add another section that allows users to freely insert fields with another actionButton (Section B). So Section B is within Section A.
Using the technique quoted above, it looks like I need to nest an observeEvent({}) within an observeEvent({}), but when I did so, I got this error: Error in as.vector: cannot coerce type 'environment' to vector of type 'character'.
Anyone has got any ideas how to get around? Here is the relevant code:
server part:
################################# Additional Tables ############################
### UI part
ids <<- NULL
idsR <- reactiveValues(v=c())
idsa <<- NULL
idsaR <- reactiveValues(v=c())
observeEvent(input$addTable,{
if (is.null(ids)){
ids <<- 1
idsR$v <- c()
}else{
ids <<- c(ids, max(ids)+1)
}
idsR$v <- ids
output$additionalTables <- renderUI({
lapply(1:length(ids),function(i){
## Input: Joining condition 1 for the first table
output[[paste0("joinCondition_1_a_additional",ids[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_a_additional",ids[i]), HTML("Column to Join (1st Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input$table) & condition1(), 2]))))
})
## Input: Joining condition 1 for the additional table
output[[paste0("joinCondition_1_b_additional",ids[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_b_additional",ids[i]), HTML("Column to Join (Additional Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2]))))
})
## Input: Tables in the first table's schema
output[[paste0("additional_table",ids[i])]] <- renderUI({
selectInput(paste0("additional_table",ids[i]), HTML("Table <font size = '3' color = 'red'>*</font>"), choices = as.list(sort(unique(allTableNames[allTableNames[,1] == trimws(input$schema), 2]))))
})
## Input: Columns in the additional table
output[[paste0("additional_column",ids[i])]] <- renderUI({
selectInput(paste0("additional_column",ids[i]), HTML("Non-aggregate columns <font size = '3' color = 'red'>*</font>"), multiple = TRUE, choices = as.list(c(
####Bill suggested not allowing users to select all columns #"*",
sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2 ])))))
})
tagList(
tags$hr(style="height:1px;border:none;background-color:#D1D1D1;" ),
tags$h4(sprintf("Additional Table #%d",ids[i]),align = "center", style="color:#2955A0;font-weight:bold; font-family:times;"),
fluidRow(
column(
# Input: joining method
radioButtons(inputId = paste0("joiningMethod",ids[i]), label = HTML("Method <font size = '3' color = 'red'>*</font>"), choices = c("left", "inner")), width = 4),
column(
# Input: the origin of the additional table
radioButtons(inputId = paste0("tableOrigin",ids[i]), label = HTML("Is the additional table in CCW or external? <font size = '3' color = 'red'>*</font>"), choices = c("CCW", "external")), width = 8)),
# If CCW
conditionalPanel(
condition = paste0("input.",paste0("tableOrigin",ids[i]),"== 'CCW'"),
# Input: table for the additional table
uiOutput(outputId = paste0("additional_table",ids[i])),
# Input: columns for the additional table
uiOutput(outputId = paste0("additional_column",ids[i])),
tags$h4("Joining Condition",align = "center", style="color:#2955A0;font-weight:bold; font-family:times;"),
fluidRow(
column(
# Input: joining condition for the first table
uiOutput(outputId = paste0("joinCondition_1_a_additional",ids[i])), width = 6),
column(
# Input: joining condition for the additional table
uiOutput(outputId = paste0("joinCondition_1_b_additional",ids[i])), width = 6)
),
uiOutput(outputId = paste0("additionaljoinCondition_additionalTable",ids[i])),
fluidRow(
column(12, align="center", offset = 0, actionButton(inputId = paste0("addjoiningCondition_additionalTable", ids[i]),"Add Another Joining Condition?", style="color: #fff; text-align: center; background-color: #337ab7; border-color: #2e6da4"))
)
),
# If External
conditionalPanel(
condition = paste0("input.",paste0("tableOrigin",ids[i]),"== 'external'"),
# file upload UI for the additional table
fileInput(inputId = paste0("additionalTable",ids[i]), label = "Table to join with (csv file, with header in the first row)", accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv"))
)
)
## Additional Joining conditions for Additional Tables ##
observeEvent(input[[paste0("addjoiningCondition_additionalTable", ids[i])]],{
if (is.null(idsa)){
idsa <<- 1
idsaR$v <- c()
}else{
idsa <<- c(idsa, max(idsa)+1)
}
idsaR$v <- idsa
output[[paste0("additionaljoinCondition_additionalTable", ids[i])]] <- renderUI({
lapply(1:length(idsa),function(i){
## Input: Joining condition 1 for the first table
output[[paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i]), HTML("Column to Join (1st Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input$table) & condition1(), 2]))))
})
## Input: Joining condition 1 for the additional table
output[[paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i])]] <- renderUI({
selectInput(paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i]), HTML("Column to Join (Additional Table) <font size = '3' color = 'red'>*</font>"), multiple = FALSE, choices = as.list(sort(unique(partColumnNames()[partColumnNames()[, 1] == trimws(input[[paste0("additional_table",ids[i])]]) & condition1(), 2]))))
})
tagList(
fluidRow(
column(
# Input: joining condition for the first table --> Input: "output$joinCondition_1_a"
uiOutput(outputId = paste0("joinCondition_1_a_additional_additionaltable_idsa",idsa[i])), width = 6),
column(
# Input: joining condition for the second table --> Input: "output$joinCondition_1_b"
uiOutput(outputId = paste0("joinCondition_1_b_additional_additionaltable_idsa",idsa[i])), width = 6)
)
)
})
})
})
})
})
})
Since I used uiOutput to display the objects, a lot of the inputs were moved to server.R as wrapped in renderUI({}). The relevant ui part of the code only has the following:
uiOutput("additionaljoinCondition"),
fluidRow(
column(12, align="center", offset = 0, actionButton("addjoiningCondition","Add Another Joining Condition?", style="color: #fff; text-align: center; background-color: #337ab7; border-color: #2e6da4")))
),
r shiny
r shiny
edited Nov 21 '18 at 5:05
Ying Xue
asked Nov 20 '18 at 23:23
Ying XueYing Xue
12
12
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
More Info from the OP: I made a mockup app using the example in the quoted thread. For this particular example, the goal is to allow users to add multiple comments by hitting the "Add Comment" button under each textbox that they have created using the "Add Text" button. Now, with observeEvent({}) nested, I got the same error: Error in as.vector: cannot coerce type 'environment' to vector of type 'character'. If you can figure out the solution for the mockup, I can extend it to my original code.
ui <- shinyUI(fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
actionButton("addText","Add Text"),
uiOutput("txtOutput"),
actionButton("getTexts","Get Input Values")
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("txtOut"),
verbatimTextOutput("cmtOut")
)
)))
server <- shinyServer(function(input,output,session){
ids <<- NULL
observeEvent(input$addText,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
idsa <<- NULL
output$txtOutput <- renderUI({
lapply(1:length(ids),function(i){
textInput(paste0("txtInput",ids[i]), sprintf("Text Input #%d",ids[i]))
uiOutput(outputId = paste0("cmtOutput", ids[i]))
actionButton(inputId = paste0("addComment", ids[i]), "Add Comment")
observeEvent(input[[paste0("addComment",ids[i])]],{
if (is.null(idsa)){
idsa <<- 1
}else{
idsa <<- c(idsa, max(idsa)+1)
}
output[[paste0("cmtOutput",ids[i])]] <- renderUI({
lapply(1:length(idsa), function(i){
textInput(paste0("cmtInput", ids[i], "_", idsa[i]), sprintf("Comment Input #%d", idsa[i]))
})
})
})
})
})
})
observeEvent(input$getTexts,{
if(is.null(ids)){
output$txtOut <- renderPrint({"No textboxes"})
output$cmtOut <- renderPrint({"No comments"})
}else{
txtOut <- list()
# Get ids for textboxes
txtbox_ids <- sapply(1:length(ids),function(i){
paste0("txtInput",ids[i],sep="")
})
# Get values
for(i in 1:length(txtbox_ids)){
txtOut[[i]] <- sprintf("Txtbox #%d has value: %s",i,input[[ txtbox_ids[i] ]])
}
output$txtOut <- renderPrint({txtOut})
if(is.null(idsa)){
output$cmtOut <- renderPrint({"No comments"})
}else{
cmtOut <- list()
# Get ids for textboxes
cmtbox_ids <- sapply(1:length(idsa),function(i){
paste0("cmtInput",ids[i], "_", idsa[i],sep="")
})
# Get values
for(i in 1:length(cmtbox_ids)){
cmtOut[[i]] <- sprintf("Comment box #%d has value: %s",i,input[[ cmtbox_ids[i] ]])
}
output$cmtOut <- renderPrint({cmtOut})
}
}
})
})
shinyApp(ui=ui,server=server)
add a comment |
I figured it out myself. Just posting for anyone who encounters similar issues. Below is the code for the mockup.
Notice the use of
if (idsc[i] != input[[paste0("addComment", idsR$v[i])]])
With this syntax missing, when you click "Add Text" twice, and "Add Comment" once for the first textbox, you will see two comments been added.
Also notice the use of
if (length(idsaR$v[[i]]) != 0){
, if omitting that, after you add comments for textbox #2 and want to go back add comments for textbox #1, there will be an error.
idsaR$v[[i]] <<- c(idsaR$v[[i]], max(idsaR$v[[i]])+1)
}
else{
idsaR$v[[i]] <<- c(1)
}
ui <- shinyUI(
fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
actionButton("addText","Add Text"),
uiOutput("txtOutput"),
actionButton("getTexts","Get Input Values")
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("txtOut"),
verbatimTextOutput("cmtOut")
)
)))
server <- shinyServer(function(input,output,session){
ids <<- NULL
idsR <<- reactiveValues(v = c())
idsaR <<- reactiveValues(v = list())
idsc <<- c()
observeEvent(input$addText,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
idsR$v <<- ids
output$txtOutput <- renderUI({
lapply(1:length(ids),function(i){
tagList(
textInput(paste0("txtInput",idsR$v[i]), sprintf("Text Input #%d",idsR$v[i])),
uiOutput(outputId = paste0("cmtOutput", idsR$v[i])),
actionButton(inputId = paste0("addComment", idsR$v[i]), "Add Comment")
)
})
})
})
idsc <<- c()
observe({
if (length(idsR$v)!= 0){
lapply(1:length(idsR$v), function(i){
idsc[i] <<- 0
observeEvent(input[[paste0("addComment", idsR$v[i])]],{
if (idsc[i] != input[[paste0("addComment", idsR$v[i])]]){
if (length(idsaR$v) < i ){
idsaR$v[[i]] <<- c(1)
}else{
if (length(idsaR$v[[i]]) != 0){
idsaR$v[[i]] <<- c(idsaR$v[[i]], max(idsaR$v[[i]])+1)
}
else{
idsaR$v[[i]] <<- c(1)
}
}
}
idsc[i] <<- input[[paste0("addComment", idsR$v[i])]]
output[[paste0("cmtOutput",idsR$v[i])]] <- renderUI({
lapply(1:length(idsaR$v[[i]]), function(j){
textInput(paste0("cmtInput", idsR$v[i], "_", idsaR$v[[i]][j]), sprintf("Comment Input #%d, #%s", idsR$v[i], idsaR$v[[i]][j]))
})
})
})
})
}
})
observeEvent(input$getTexts,{
if(is.null(idsR$v)){
output$txtOut <- renderPrint({"No textboxes"})
output$cmtOut <- renderPrint({"No comments"})
}else{
txtOut <- list()
cmtOut <- list()
cmtbox_ids <- list()
# Get ids for textboxes
txtbox_ids <- sapply(1:length(idsR$v),function(i){
paste0("txtInput",idsR$v[i],sep="")
})
# Get values
for(i in 1:length(txtbox_ids)){
txtOut[[i]] <- sprintf("Txtbox #%d has value: %s",i,input[[ txtbox_ids[i] ]])
if(is.null(idsaR$v)){
cmtOut <- list("No comments")
}else{
cmtOut[[i]] <- list()
if (length(idsaR$v) >= i){
# Get ids for commentboxes for the ith textbox
cmtbox_ids[[i]] <- sapply(1:length(idsaR$v[[i]]),function(j){
paste0("cmtInput",idsR$v[i], "_", idsaR$v[[i]][j])
})
# Get values
for (j in 1:length(cmtbox_ids[[i]])){
if(is.null(idsaR$v[[i]])){
cmtOut[[i]] <- c("No comments")
}else{
cmtOut[[i]][j] <- sprintf("Comment box #%d has value: %s",j,input[[ cmtbox_ids[[i]][j] ]])
}
}
}else{
cmtOut[[i]] <- c("No comments")
}
}
}
output$txtOut <- renderPrint({txtOut})
output$cmtOut <- renderPrint({cmtOut})
}
})
})
shinyApp(ui=ui,server=server)
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403117%2fnesting-observeevent-within-observeevent-in-r-shiny%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
More Info from the OP: I made a mockup app using the example in the quoted thread. For this particular example, the goal is to allow users to add multiple comments by hitting the "Add Comment" button under each textbox that they have created using the "Add Text" button. Now, with observeEvent({}) nested, I got the same error: Error in as.vector: cannot coerce type 'environment' to vector of type 'character'. If you can figure out the solution for the mockup, I can extend it to my original code.
ui <- shinyUI(fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
actionButton("addText","Add Text"),
uiOutput("txtOutput"),
actionButton("getTexts","Get Input Values")
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("txtOut"),
verbatimTextOutput("cmtOut")
)
)))
server <- shinyServer(function(input,output,session){
ids <<- NULL
observeEvent(input$addText,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
idsa <<- NULL
output$txtOutput <- renderUI({
lapply(1:length(ids),function(i){
textInput(paste0("txtInput",ids[i]), sprintf("Text Input #%d",ids[i]))
uiOutput(outputId = paste0("cmtOutput", ids[i]))
actionButton(inputId = paste0("addComment", ids[i]), "Add Comment")
observeEvent(input[[paste0("addComment",ids[i])]],{
if (is.null(idsa)){
idsa <<- 1
}else{
idsa <<- c(idsa, max(idsa)+1)
}
output[[paste0("cmtOutput",ids[i])]] <- renderUI({
lapply(1:length(idsa), function(i){
textInput(paste0("cmtInput", ids[i], "_", idsa[i]), sprintf("Comment Input #%d", idsa[i]))
})
})
})
})
})
})
observeEvent(input$getTexts,{
if(is.null(ids)){
output$txtOut <- renderPrint({"No textboxes"})
output$cmtOut <- renderPrint({"No comments"})
}else{
txtOut <- list()
# Get ids for textboxes
txtbox_ids <- sapply(1:length(ids),function(i){
paste0("txtInput",ids[i],sep="")
})
# Get values
for(i in 1:length(txtbox_ids)){
txtOut[[i]] <- sprintf("Txtbox #%d has value: %s",i,input[[ txtbox_ids[i] ]])
}
output$txtOut <- renderPrint({txtOut})
if(is.null(idsa)){
output$cmtOut <- renderPrint({"No comments"})
}else{
cmtOut <- list()
# Get ids for textboxes
cmtbox_ids <- sapply(1:length(idsa),function(i){
paste0("cmtInput",ids[i], "_", idsa[i],sep="")
})
# Get values
for(i in 1:length(cmtbox_ids)){
cmtOut[[i]] <- sprintf("Comment box #%d has value: %s",i,input[[ cmtbox_ids[i] ]])
}
output$cmtOut <- renderPrint({cmtOut})
}
}
})
})
shinyApp(ui=ui,server=server)
add a comment |
More Info from the OP: I made a mockup app using the example in the quoted thread. For this particular example, the goal is to allow users to add multiple comments by hitting the "Add Comment" button under each textbox that they have created using the "Add Text" button. Now, with observeEvent({}) nested, I got the same error: Error in as.vector: cannot coerce type 'environment' to vector of type 'character'. If you can figure out the solution for the mockup, I can extend it to my original code.
ui <- shinyUI(fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
actionButton("addText","Add Text"),
uiOutput("txtOutput"),
actionButton("getTexts","Get Input Values")
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("txtOut"),
verbatimTextOutput("cmtOut")
)
)))
server <- shinyServer(function(input,output,session){
ids <<- NULL
observeEvent(input$addText,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
idsa <<- NULL
output$txtOutput <- renderUI({
lapply(1:length(ids),function(i){
textInput(paste0("txtInput",ids[i]), sprintf("Text Input #%d",ids[i]))
uiOutput(outputId = paste0("cmtOutput", ids[i]))
actionButton(inputId = paste0("addComment", ids[i]), "Add Comment")
observeEvent(input[[paste0("addComment",ids[i])]],{
if (is.null(idsa)){
idsa <<- 1
}else{
idsa <<- c(idsa, max(idsa)+1)
}
output[[paste0("cmtOutput",ids[i])]] <- renderUI({
lapply(1:length(idsa), function(i){
textInput(paste0("cmtInput", ids[i], "_", idsa[i]), sprintf("Comment Input #%d", idsa[i]))
})
})
})
})
})
})
observeEvent(input$getTexts,{
if(is.null(ids)){
output$txtOut <- renderPrint({"No textboxes"})
output$cmtOut <- renderPrint({"No comments"})
}else{
txtOut <- list()
# Get ids for textboxes
txtbox_ids <- sapply(1:length(ids),function(i){
paste0("txtInput",ids[i],sep="")
})
# Get values
for(i in 1:length(txtbox_ids)){
txtOut[[i]] <- sprintf("Txtbox #%d has value: %s",i,input[[ txtbox_ids[i] ]])
}
output$txtOut <- renderPrint({txtOut})
if(is.null(idsa)){
output$cmtOut <- renderPrint({"No comments"})
}else{
cmtOut <- list()
# Get ids for textboxes
cmtbox_ids <- sapply(1:length(idsa),function(i){
paste0("cmtInput",ids[i], "_", idsa[i],sep="")
})
# Get values
for(i in 1:length(cmtbox_ids)){
cmtOut[[i]] <- sprintf("Comment box #%d has value: %s",i,input[[ cmtbox_ids[i] ]])
}
output$cmtOut <- renderPrint({cmtOut})
}
}
})
})
shinyApp(ui=ui,server=server)
add a comment |
More Info from the OP: I made a mockup app using the example in the quoted thread. For this particular example, the goal is to allow users to add multiple comments by hitting the "Add Comment" button under each textbox that they have created using the "Add Text" button. Now, with observeEvent({}) nested, I got the same error: Error in as.vector: cannot coerce type 'environment' to vector of type 'character'. If you can figure out the solution for the mockup, I can extend it to my original code.
ui <- shinyUI(fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
actionButton("addText","Add Text"),
uiOutput("txtOutput"),
actionButton("getTexts","Get Input Values")
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("txtOut"),
verbatimTextOutput("cmtOut")
)
)))
server <- shinyServer(function(input,output,session){
ids <<- NULL
observeEvent(input$addText,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
idsa <<- NULL
output$txtOutput <- renderUI({
lapply(1:length(ids),function(i){
textInput(paste0("txtInput",ids[i]), sprintf("Text Input #%d",ids[i]))
uiOutput(outputId = paste0("cmtOutput", ids[i]))
actionButton(inputId = paste0("addComment", ids[i]), "Add Comment")
observeEvent(input[[paste0("addComment",ids[i])]],{
if (is.null(idsa)){
idsa <<- 1
}else{
idsa <<- c(idsa, max(idsa)+1)
}
output[[paste0("cmtOutput",ids[i])]] <- renderUI({
lapply(1:length(idsa), function(i){
textInput(paste0("cmtInput", ids[i], "_", idsa[i]), sprintf("Comment Input #%d", idsa[i]))
})
})
})
})
})
})
observeEvent(input$getTexts,{
if(is.null(ids)){
output$txtOut <- renderPrint({"No textboxes"})
output$cmtOut <- renderPrint({"No comments"})
}else{
txtOut <- list()
# Get ids for textboxes
txtbox_ids <- sapply(1:length(ids),function(i){
paste0("txtInput",ids[i],sep="")
})
# Get values
for(i in 1:length(txtbox_ids)){
txtOut[[i]] <- sprintf("Txtbox #%d has value: %s",i,input[[ txtbox_ids[i] ]])
}
output$txtOut <- renderPrint({txtOut})
if(is.null(idsa)){
output$cmtOut <- renderPrint({"No comments"})
}else{
cmtOut <- list()
# Get ids for textboxes
cmtbox_ids <- sapply(1:length(idsa),function(i){
paste0("cmtInput",ids[i], "_", idsa[i],sep="")
})
# Get values
for(i in 1:length(cmtbox_ids)){
cmtOut[[i]] <- sprintf("Comment box #%d has value: %s",i,input[[ cmtbox_ids[i] ]])
}
output$cmtOut <- renderPrint({cmtOut})
}
}
})
})
shinyApp(ui=ui,server=server)
More Info from the OP: I made a mockup app using the example in the quoted thread. For this particular example, the goal is to allow users to add multiple comments by hitting the "Add Comment" button under each textbox that they have created using the "Add Text" button. Now, with observeEvent({}) nested, I got the same error: Error in as.vector: cannot coerce type 'environment' to vector of type 'character'. If you can figure out the solution for the mockup, I can extend it to my original code.
ui <- shinyUI(fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
actionButton("addText","Add Text"),
uiOutput("txtOutput"),
actionButton("getTexts","Get Input Values")
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("txtOut"),
verbatimTextOutput("cmtOut")
)
)))
server <- shinyServer(function(input,output,session){
ids <<- NULL
observeEvent(input$addText,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
idsa <<- NULL
output$txtOutput <- renderUI({
lapply(1:length(ids),function(i){
textInput(paste0("txtInput",ids[i]), sprintf("Text Input #%d",ids[i]))
uiOutput(outputId = paste0("cmtOutput", ids[i]))
actionButton(inputId = paste0("addComment", ids[i]), "Add Comment")
observeEvent(input[[paste0("addComment",ids[i])]],{
if (is.null(idsa)){
idsa <<- 1
}else{
idsa <<- c(idsa, max(idsa)+1)
}
output[[paste0("cmtOutput",ids[i])]] <- renderUI({
lapply(1:length(idsa), function(i){
textInput(paste0("cmtInput", ids[i], "_", idsa[i]), sprintf("Comment Input #%d", idsa[i]))
})
})
})
})
})
})
observeEvent(input$getTexts,{
if(is.null(ids)){
output$txtOut <- renderPrint({"No textboxes"})
output$cmtOut <- renderPrint({"No comments"})
}else{
txtOut <- list()
# Get ids for textboxes
txtbox_ids <- sapply(1:length(ids),function(i){
paste0("txtInput",ids[i],sep="")
})
# Get values
for(i in 1:length(txtbox_ids)){
txtOut[[i]] <- sprintf("Txtbox #%d has value: %s",i,input[[ txtbox_ids[i] ]])
}
output$txtOut <- renderPrint({txtOut})
if(is.null(idsa)){
output$cmtOut <- renderPrint({"No comments"})
}else{
cmtOut <- list()
# Get ids for textboxes
cmtbox_ids <- sapply(1:length(idsa),function(i){
paste0("cmtInput",ids[i], "_", idsa[i],sep="")
})
# Get values
for(i in 1:length(cmtbox_ids)){
cmtOut[[i]] <- sprintf("Comment box #%d has value: %s",i,input[[ cmtbox_ids[i] ]])
}
output$cmtOut <- renderPrint({cmtOut})
}
}
})
})
shinyApp(ui=ui,server=server)
edited Nov 26 '18 at 16:36
answered Nov 21 '18 at 4:44
Ying XueYing Xue
12
12
add a comment |
add a comment |
I figured it out myself. Just posting for anyone who encounters similar issues. Below is the code for the mockup.
Notice the use of
if (idsc[i] != input[[paste0("addComment", idsR$v[i])]])
With this syntax missing, when you click "Add Text" twice, and "Add Comment" once for the first textbox, you will see two comments been added.
Also notice the use of
if (length(idsaR$v[[i]]) != 0){
, if omitting that, after you add comments for textbox #2 and want to go back add comments for textbox #1, there will be an error.
idsaR$v[[i]] <<- c(idsaR$v[[i]], max(idsaR$v[[i]])+1)
}
else{
idsaR$v[[i]] <<- c(1)
}
ui <- shinyUI(
fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
actionButton("addText","Add Text"),
uiOutput("txtOutput"),
actionButton("getTexts","Get Input Values")
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("txtOut"),
verbatimTextOutput("cmtOut")
)
)))
server <- shinyServer(function(input,output,session){
ids <<- NULL
idsR <<- reactiveValues(v = c())
idsaR <<- reactiveValues(v = list())
idsc <<- c()
observeEvent(input$addText,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
idsR$v <<- ids
output$txtOutput <- renderUI({
lapply(1:length(ids),function(i){
tagList(
textInput(paste0("txtInput",idsR$v[i]), sprintf("Text Input #%d",idsR$v[i])),
uiOutput(outputId = paste0("cmtOutput", idsR$v[i])),
actionButton(inputId = paste0("addComment", idsR$v[i]), "Add Comment")
)
})
})
})
idsc <<- c()
observe({
if (length(idsR$v)!= 0){
lapply(1:length(idsR$v), function(i){
idsc[i] <<- 0
observeEvent(input[[paste0("addComment", idsR$v[i])]],{
if (idsc[i] != input[[paste0("addComment", idsR$v[i])]]){
if (length(idsaR$v) < i ){
idsaR$v[[i]] <<- c(1)
}else{
if (length(idsaR$v[[i]]) != 0){
idsaR$v[[i]] <<- c(idsaR$v[[i]], max(idsaR$v[[i]])+1)
}
else{
idsaR$v[[i]] <<- c(1)
}
}
}
idsc[i] <<- input[[paste0("addComment", idsR$v[i])]]
output[[paste0("cmtOutput",idsR$v[i])]] <- renderUI({
lapply(1:length(idsaR$v[[i]]), function(j){
textInput(paste0("cmtInput", idsR$v[i], "_", idsaR$v[[i]][j]), sprintf("Comment Input #%d, #%s", idsR$v[i], idsaR$v[[i]][j]))
})
})
})
})
}
})
observeEvent(input$getTexts,{
if(is.null(idsR$v)){
output$txtOut <- renderPrint({"No textboxes"})
output$cmtOut <- renderPrint({"No comments"})
}else{
txtOut <- list()
cmtOut <- list()
cmtbox_ids <- list()
# Get ids for textboxes
txtbox_ids <- sapply(1:length(idsR$v),function(i){
paste0("txtInput",idsR$v[i],sep="")
})
# Get values
for(i in 1:length(txtbox_ids)){
txtOut[[i]] <- sprintf("Txtbox #%d has value: %s",i,input[[ txtbox_ids[i] ]])
if(is.null(idsaR$v)){
cmtOut <- list("No comments")
}else{
cmtOut[[i]] <- list()
if (length(idsaR$v) >= i){
# Get ids for commentboxes for the ith textbox
cmtbox_ids[[i]] <- sapply(1:length(idsaR$v[[i]]),function(j){
paste0("cmtInput",idsR$v[i], "_", idsaR$v[[i]][j])
})
# Get values
for (j in 1:length(cmtbox_ids[[i]])){
if(is.null(idsaR$v[[i]])){
cmtOut[[i]] <- c("No comments")
}else{
cmtOut[[i]][j] <- sprintf("Comment box #%d has value: %s",j,input[[ cmtbox_ids[[i]][j] ]])
}
}
}else{
cmtOut[[i]] <- c("No comments")
}
}
}
output$txtOut <- renderPrint({txtOut})
output$cmtOut <- renderPrint({cmtOut})
}
})
})
shinyApp(ui=ui,server=server)
add a comment |
I figured it out myself. Just posting for anyone who encounters similar issues. Below is the code for the mockup.
Notice the use of
if (idsc[i] != input[[paste0("addComment", idsR$v[i])]])
With this syntax missing, when you click "Add Text" twice, and "Add Comment" once for the first textbox, you will see two comments been added.
Also notice the use of
if (length(idsaR$v[[i]]) != 0){
, if omitting that, after you add comments for textbox #2 and want to go back add comments for textbox #1, there will be an error.
idsaR$v[[i]] <<- c(idsaR$v[[i]], max(idsaR$v[[i]])+1)
}
else{
idsaR$v[[i]] <<- c(1)
}
ui <- shinyUI(
fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
actionButton("addText","Add Text"),
uiOutput("txtOutput"),
actionButton("getTexts","Get Input Values")
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("txtOut"),
verbatimTextOutput("cmtOut")
)
)))
server <- shinyServer(function(input,output,session){
ids <<- NULL
idsR <<- reactiveValues(v = c())
idsaR <<- reactiveValues(v = list())
idsc <<- c()
observeEvent(input$addText,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
idsR$v <<- ids
output$txtOutput <- renderUI({
lapply(1:length(ids),function(i){
tagList(
textInput(paste0("txtInput",idsR$v[i]), sprintf("Text Input #%d",idsR$v[i])),
uiOutput(outputId = paste0("cmtOutput", idsR$v[i])),
actionButton(inputId = paste0("addComment", idsR$v[i]), "Add Comment")
)
})
})
})
idsc <<- c()
observe({
if (length(idsR$v)!= 0){
lapply(1:length(idsR$v), function(i){
idsc[i] <<- 0
observeEvent(input[[paste0("addComment", idsR$v[i])]],{
if (idsc[i] != input[[paste0("addComment", idsR$v[i])]]){
if (length(idsaR$v) < i ){
idsaR$v[[i]] <<- c(1)
}else{
if (length(idsaR$v[[i]]) != 0){
idsaR$v[[i]] <<- c(idsaR$v[[i]], max(idsaR$v[[i]])+1)
}
else{
idsaR$v[[i]] <<- c(1)
}
}
}
idsc[i] <<- input[[paste0("addComment", idsR$v[i])]]
output[[paste0("cmtOutput",idsR$v[i])]] <- renderUI({
lapply(1:length(idsaR$v[[i]]), function(j){
textInput(paste0("cmtInput", idsR$v[i], "_", idsaR$v[[i]][j]), sprintf("Comment Input #%d, #%s", idsR$v[i], idsaR$v[[i]][j]))
})
})
})
})
}
})
observeEvent(input$getTexts,{
if(is.null(idsR$v)){
output$txtOut <- renderPrint({"No textboxes"})
output$cmtOut <- renderPrint({"No comments"})
}else{
txtOut <- list()
cmtOut <- list()
cmtbox_ids <- list()
# Get ids for textboxes
txtbox_ids <- sapply(1:length(idsR$v),function(i){
paste0("txtInput",idsR$v[i],sep="")
})
# Get values
for(i in 1:length(txtbox_ids)){
txtOut[[i]] <- sprintf("Txtbox #%d has value: %s",i,input[[ txtbox_ids[i] ]])
if(is.null(idsaR$v)){
cmtOut <- list("No comments")
}else{
cmtOut[[i]] <- list()
if (length(idsaR$v) >= i){
# Get ids for commentboxes for the ith textbox
cmtbox_ids[[i]] <- sapply(1:length(idsaR$v[[i]]),function(j){
paste0("cmtInput",idsR$v[i], "_", idsaR$v[[i]][j])
})
# Get values
for (j in 1:length(cmtbox_ids[[i]])){
if(is.null(idsaR$v[[i]])){
cmtOut[[i]] <- c("No comments")
}else{
cmtOut[[i]][j] <- sprintf("Comment box #%d has value: %s",j,input[[ cmtbox_ids[[i]][j] ]])
}
}
}else{
cmtOut[[i]] <- c("No comments")
}
}
}
output$txtOut <- renderPrint({txtOut})
output$cmtOut <- renderPrint({cmtOut})
}
})
})
shinyApp(ui=ui,server=server)
add a comment |
I figured it out myself. Just posting for anyone who encounters similar issues. Below is the code for the mockup.
Notice the use of
if (idsc[i] != input[[paste0("addComment", idsR$v[i])]])
With this syntax missing, when you click "Add Text" twice, and "Add Comment" once for the first textbox, you will see two comments been added.
Also notice the use of
if (length(idsaR$v[[i]]) != 0){
, if omitting that, after you add comments for textbox #2 and want to go back add comments for textbox #1, there will be an error.
idsaR$v[[i]] <<- c(idsaR$v[[i]], max(idsaR$v[[i]])+1)
}
else{
idsaR$v[[i]] <<- c(1)
}
ui <- shinyUI(
fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
actionButton("addText","Add Text"),
uiOutput("txtOutput"),
actionButton("getTexts","Get Input Values")
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("txtOut"),
verbatimTextOutput("cmtOut")
)
)))
server <- shinyServer(function(input,output,session){
ids <<- NULL
idsR <<- reactiveValues(v = c())
idsaR <<- reactiveValues(v = list())
idsc <<- c()
observeEvent(input$addText,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
idsR$v <<- ids
output$txtOutput <- renderUI({
lapply(1:length(ids),function(i){
tagList(
textInput(paste0("txtInput",idsR$v[i]), sprintf("Text Input #%d",idsR$v[i])),
uiOutput(outputId = paste0("cmtOutput", idsR$v[i])),
actionButton(inputId = paste0("addComment", idsR$v[i]), "Add Comment")
)
})
})
})
idsc <<- c()
observe({
if (length(idsR$v)!= 0){
lapply(1:length(idsR$v), function(i){
idsc[i] <<- 0
observeEvent(input[[paste0("addComment", idsR$v[i])]],{
if (idsc[i] != input[[paste0("addComment", idsR$v[i])]]){
if (length(idsaR$v) < i ){
idsaR$v[[i]] <<- c(1)
}else{
if (length(idsaR$v[[i]]) != 0){
idsaR$v[[i]] <<- c(idsaR$v[[i]], max(idsaR$v[[i]])+1)
}
else{
idsaR$v[[i]] <<- c(1)
}
}
}
idsc[i] <<- input[[paste0("addComment", idsR$v[i])]]
output[[paste0("cmtOutput",idsR$v[i])]] <- renderUI({
lapply(1:length(idsaR$v[[i]]), function(j){
textInput(paste0("cmtInput", idsR$v[i], "_", idsaR$v[[i]][j]), sprintf("Comment Input #%d, #%s", idsR$v[i], idsaR$v[[i]][j]))
})
})
})
})
}
})
observeEvent(input$getTexts,{
if(is.null(idsR$v)){
output$txtOut <- renderPrint({"No textboxes"})
output$cmtOut <- renderPrint({"No comments"})
}else{
txtOut <- list()
cmtOut <- list()
cmtbox_ids <- list()
# Get ids for textboxes
txtbox_ids <- sapply(1:length(idsR$v),function(i){
paste0("txtInput",idsR$v[i],sep="")
})
# Get values
for(i in 1:length(txtbox_ids)){
txtOut[[i]] <- sprintf("Txtbox #%d has value: %s",i,input[[ txtbox_ids[i] ]])
if(is.null(idsaR$v)){
cmtOut <- list("No comments")
}else{
cmtOut[[i]] <- list()
if (length(idsaR$v) >= i){
# Get ids for commentboxes for the ith textbox
cmtbox_ids[[i]] <- sapply(1:length(idsaR$v[[i]]),function(j){
paste0("cmtInput",idsR$v[i], "_", idsaR$v[[i]][j])
})
# Get values
for (j in 1:length(cmtbox_ids[[i]])){
if(is.null(idsaR$v[[i]])){
cmtOut[[i]] <- c("No comments")
}else{
cmtOut[[i]][j] <- sprintf("Comment box #%d has value: %s",j,input[[ cmtbox_ids[[i]][j] ]])
}
}
}else{
cmtOut[[i]] <- c("No comments")
}
}
}
output$txtOut <- renderPrint({txtOut})
output$cmtOut <- renderPrint({cmtOut})
}
})
})
shinyApp(ui=ui,server=server)
I figured it out myself. Just posting for anyone who encounters similar issues. Below is the code for the mockup.
Notice the use of
if (idsc[i] != input[[paste0("addComment", idsR$v[i])]])
With this syntax missing, when you click "Add Text" twice, and "Add Comment" once for the first textbox, you will see two comments been added.
Also notice the use of
if (length(idsaR$v[[i]]) != 0){
, if omitting that, after you add comments for textbox #2 and want to go back add comments for textbox #1, there will be an error.
idsaR$v[[i]] <<- c(idsaR$v[[i]], max(idsaR$v[[i]])+1)
}
else{
idsaR$v[[i]] <<- c(1)
}
ui <- shinyUI(
fluidPage(
titlePanel(""),
sidebarLayout(
sidebarPanel(
actionButton("addText","Add Text"),
uiOutput("txtOutput"),
actionButton("getTexts","Get Input Values")
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("txtOut"),
verbatimTextOutput("cmtOut")
)
)))
server <- shinyServer(function(input,output,session){
ids <<- NULL
idsR <<- reactiveValues(v = c())
idsaR <<- reactiveValues(v = list())
idsc <<- c()
observeEvent(input$addText,{
if (is.null(ids)){
ids <<- 1
}else{
ids <<- c(ids, max(ids)+1)
}
idsR$v <<- ids
output$txtOutput <- renderUI({
lapply(1:length(ids),function(i){
tagList(
textInput(paste0("txtInput",idsR$v[i]), sprintf("Text Input #%d",idsR$v[i])),
uiOutput(outputId = paste0("cmtOutput", idsR$v[i])),
actionButton(inputId = paste0("addComment", idsR$v[i]), "Add Comment")
)
})
})
})
idsc <<- c()
observe({
if (length(idsR$v)!= 0){
lapply(1:length(idsR$v), function(i){
idsc[i] <<- 0
observeEvent(input[[paste0("addComment", idsR$v[i])]],{
if (idsc[i] != input[[paste0("addComment", idsR$v[i])]]){
if (length(idsaR$v) < i ){
idsaR$v[[i]] <<- c(1)
}else{
if (length(idsaR$v[[i]]) != 0){
idsaR$v[[i]] <<- c(idsaR$v[[i]], max(idsaR$v[[i]])+1)
}
else{
idsaR$v[[i]] <<- c(1)
}
}
}
idsc[i] <<- input[[paste0("addComment", idsR$v[i])]]
output[[paste0("cmtOutput",idsR$v[i])]] <- renderUI({
lapply(1:length(idsaR$v[[i]]), function(j){
textInput(paste0("cmtInput", idsR$v[i], "_", idsaR$v[[i]][j]), sprintf("Comment Input #%d, #%s", idsR$v[i], idsaR$v[[i]][j]))
})
})
})
})
}
})
observeEvent(input$getTexts,{
if(is.null(idsR$v)){
output$txtOut <- renderPrint({"No textboxes"})
output$cmtOut <- renderPrint({"No comments"})
}else{
txtOut <- list()
cmtOut <- list()
cmtbox_ids <- list()
# Get ids for textboxes
txtbox_ids <- sapply(1:length(idsR$v),function(i){
paste0("txtInput",idsR$v[i],sep="")
})
# Get values
for(i in 1:length(txtbox_ids)){
txtOut[[i]] <- sprintf("Txtbox #%d has value: %s",i,input[[ txtbox_ids[i] ]])
if(is.null(idsaR$v)){
cmtOut <- list("No comments")
}else{
cmtOut[[i]] <- list()
if (length(idsaR$v) >= i){
# Get ids for commentboxes for the ith textbox
cmtbox_ids[[i]] <- sapply(1:length(idsaR$v[[i]]),function(j){
paste0("cmtInput",idsR$v[i], "_", idsaR$v[[i]][j])
})
# Get values
for (j in 1:length(cmtbox_ids[[i]])){
if(is.null(idsaR$v[[i]])){
cmtOut[[i]] <- c("No comments")
}else{
cmtOut[[i]][j] <- sprintf("Comment box #%d has value: %s",j,input[[ cmtbox_ids[[i]][j] ]])
}
}
}else{
cmtOut[[i]] <- c("No comments")
}
}
}
output$txtOut <- renderPrint({txtOut})
output$cmtOut <- renderPrint({cmtOut})
}
})
})
shinyApp(ui=ui,server=server)
answered Dec 6 '18 at 21:19
Ying XueYing Xue
12
12
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403117%2fnesting-observeevent-within-observeevent-in-r-shiny%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown