Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R shiny: how to not update all input elements of a matrix created in server.r (isolate not enough apparently)

Tags:

r

shiny

I am creating a matrix in server.R, whose elements are numeric inputs. (This is because the size of this matrix depends on other inputs).

However, if the user wants to change the row names for example using some of the preceding inputs, and regenerate the matrix (I isolate its creation using an actionButton and isolate()), all numeric inputs are lost. I understand this is due to the reactive nature of Shiny, but is there a way around this ?

Here is a scenario (see the picture below) (which is also provided in the code below): 2 inputs to create row names, 2 inputs to create columns, which gives a 2X2 matrix with 4 numeric inputs. The user inserts values in the first row, and then decides to change the name of the second row. The table is re-created and all numeric inputs are lost.

Here is the code:

ui = pageWithSidebar(

headerPanel("TEST"),

sidebarPanel(

helpText('These inputs create the rows of the matrix:'),
textInput('r1','','for row1'),
textInput('r2','','for row2'),

helpText('These inputs create the columns of the matrix:'),
textInput('c1','','for column1'),
textInput('c2','','for column2'),
hr(),
actionButton('create','create')
),

mainPanel(    
uiOutput('matrix'))
)

server = function(input,output){

output$matrix <- renderTable({

if (input$create == 0)
return()  

isolate({
## extract inputs
myRow_entries <- lapply(1:2, function(z) input[[paste0("r", z)]])

myCol_entries <- lapply(1:2, function(z) input[[paste0("c", z)]]) 

Row_entries <- unlist(c(do.call("c", myRow_entries)))

Col_entries <- unlist(c(do.call("c", myCol_entries)))
## End of extract inputs     

## create matrix with numeric inputs      
matrix_input <- list()

for(j in 1:2){

matrix_input[[j]] <- paste0("<input id='element",j,"_", 1:2,"' class='shiny-bound-input span6' type='number' value=''>")             
}

matrix <- data.frame(matrix_input) 

row.names(matrix) <- Row_entries
colnames(matrix) <- Col_entries
matrix
})
},sanitize.text.function = function(x) x)

}

runApp(list(ui=ui,server=server))

Should I isolate all elements of the matrix ? Is there another way ?

Any help/suggestion would be highly appreciated !

Cheers enter image description here

like image 439
user1431694 Avatar asked Dec 11 '25 06:12

user1431694


1 Answers

Even if the data frame is regenerated each time you click on the button you can for example set the input values by the "old" inputs values.

I changed your loop and set the value by the value of the previous input with the same id : value='", input[[paste0("element", i, "_", j)]]

ui = pageWithSidebar(

  headerPanel("TEST"),

  sidebarPanel(

    helpText('These inputs create the rows of the matrix:'),
    textInput('r1', '', 'for row1'),
    textInput('r2', '', 'for row2'),

    helpText('These inputs create the columns of the matrix:'),
    textInput('c1', '', 'for column1'),
    textInput('c2', '', 'for column2'),
    tags$hr(),
    actionButton('create','create')
  ),

  mainPanel(    
    uiOutput('matrix')
  )
)

server = function(input,output){

  output$matrix <- renderTable({

    if (input$create == 0)
      return()

    isolate({
      Row_entries <- sapply(1:2, function(z) input[[paste0("r", z)]])

      Col_entries <- sapply(1:2, function(z) input[[paste0("c", z)]])

      matrix <- data.frame()

      for (i in 1:2) {
        for (j in 1:2) {
          matrix[i,j] <- paste0("<input id='element", i, "_", j, "' class='shiny-bound-input span6' type='number' value='", input[[paste0("element", i, "_", j)]], "'>")            
        }
      }

      row.names(matrix) <- Row_entries
      colnames(matrix) <- Col_entries

      matrix

    })
  },sanitize.text.function = function(x) x)

}

runApp(list(ui = ui, server = server))
like image 127
Julien Navarre Avatar answered Dec 14 '25 00:12

Julien Navarre



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!