Reputation: 7830
I wonder how I can build inputs and re-use them in the same reactive function in which I created them.
For example in this data frame the 1st column is a numeric input and the last column should be the sum of the entire line.
The problem is that they are created in the same reactive function and then if I change an input value the reactive function will be re executed and all the table regenerated ... I tried to isolate row.sum
but it doesn't works. I totaly don't know how to do this.
If someone can help me ..
Here is an example :
shiny::runApp(list(
ui = basicPage(
tableOutput("table")
),
server = function(input, output, session) {
output$table <- renderTable({
mat <- matrix(c(54, 8, 26, 77, 87, 59, 92, 27, 63, 86, 18, 100, 74, 45, 46), nrow = 5, ncol = 3)
input1 <- paste0("<input id='a", 1:nrow(mat), "' class='shiny-bound-input' type='number' value=1 style='width: 50px;'>")
row.sum <- unlist(sapply(1:nrow(mat), function(i) input[[sprintf("a%d", i)]] + sum(mat[i,])))
cbind(input1, mat, row.sum)
}, sanitize.text.function = function(x) x)
}
))
Thank you for any help !
[Note that I unlist
the sapply function because the first time it's used, the numeric inputs haven't been created yet, they are all equals to NULL and then sapply returns a list of numeric(0)
which can't fit into a data frame]
Upvotes: 1
Views: 1497
Reputation: 30425
You can try something like this:
require(shiny)
runApp(list(
ui = basicPage(
tableOutput("table")
),
server = function(input, output, session) {
output$table <- renderTable({
mat <- matrix(c(54, 8, 26, 77, 87, 59, 92, 27, 63, 86, 18, 100, 74, 45, 46), nrow = 5, ncol = 3)
dumInput <- sapply(paste0('a', 1:5), function(x) input[[x]])
dumInput <- ifelse(sapply(dumInput, is.null), 1, dumInput)
input1 <- paste0("<input id='a", 1:5, "' class='shiny-bound-input' type='number' value=", dumInput, " style='width: 50px;'>" )
row.sum <- dumInput + rowSums(mat)
cbind(input1, mat, row.sum)
}, sanitize.text.function = function(x) x)
}
))
A brief explanation. What you had before was picking up a change in the input[[a*]]
inputs you created. However
it was then resetting the inputs back to 1. The example above passes on changes in your created inputs to the row sums but also conserves the changed input values.
An alternative formulation might be to seperate the logic using reactiveValues
. This could be preferable as it is possibly easier to extend for more complex examples.
shiny::runApp(list(
ui = basicPage(
tableOutput("table")
),
server = function(input, output, session) {
rv <- reactiveValues(
mat = matrix(c(54, 8, 26, 77, 87, 59, 92, 27, 63, 86, 18, 100, 74, 45, 46), nrow = 5, ncol = 3)
)
output$table <- renderTable({
dumInput <- sapply(paste0('a', 1:5), function(x) input[[x]])
dumInput <- ifelse(sapply(dumInput, is.null), 1, dumInput)
input1 <- paste0("<input id='a", 1:5, "' class='shiny-bound-input' type='number' value=", dumInput, " style='width: 50px;'>" )
rv$rowsum <- dumInput + rowSums(rv$mat)
cbind(input1, rv$mat, rv$rowsum)
}, sanitize.text.function = function(x) x)
}
))
Upvotes: 1