0

I created an app with shiny and shinyTable. It reads a csv file as data.frame and saves changes or new rows.

If I add a new row, it is saved but not shown in the table. I can only see the row in the table when I restart the app. How can I make sure that the submit button adds the row without restarting the app?

EDIT: I can generate this functionality with shiny and a "normal" table with renderTable, but I can't manage to get this working with shinyTable.

What I basically want to achieve is this functionality with shinyTable to have an editable table where I can add rows.

app.R

require(shiny)
datafile<-read.csv("data.csv", header=TRUE, sep=",", quote="")

runApp(
  list(
    ui = fluidPage(
      headerPanel('Title'),
      sidebarPanel(
    textInput("fielda", label="fielda", value=""),
    textInput("fieldb", label="fieldb", value=""),
    actionButton("addButton", "insert data")
      ),
      mainPanel(
    tableOutput("table"))
    ),

    server = function(input, output) {     
      datafile_sample <- datafile[sample(nrow(datafile)),]
      row.names(datafile_sample) <- NULL

      values <- reactiveValues()
      values$df <- datafile_sample
      addData <- observe({

    if(input$addButton > 0) {
      newLine <- isolate(c(input$fielda, input$fieldb))
      isolate(values$df <- rbind(as.matrix(values$df), unlist(newLine)))
      write.csv(values$df, file = "data.csv", row.names=F, quote=F)
    }
      })
      output$table <- renderTable({values$df}, include.rownames=F)
    }
  )
)

data.csv

fielda,fieldb
1,2                                                               
3,4
Revan
  • 2,072
  • 4
  • 26
  • 42
  • 1
    I'm trying to answer this question, but I'm a little confused by all the parts of server.R. Is it possible to create a more minimal example, with only the code related to your problem and some example data? http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – Mhairi McNeill May 25 '16 at 22:26
  • I tried to make it more clear, minimum working example with `shiny`, not with `shinytable`. – Revan May 25 '16 at 22:53

1 Answers1

2

I think I would approach this a little bit differently. As you've written your example, your data frame resulting from the read.csv shouldn't be called outside of the server. It should, itself, be reactive. In the code below, I've put it in a reactive values call, and initialized it with read.csv.

Then, when you add data to it, you can use write.table to add it to the existing file, and then update the reactive object. This should set all the pieces in motion to update automatically, regardless of what table type you use? (I'm not familiar with shinyTable, so didn't experiment with it much).

There are a few variants you can take on this. For starters, is it really necessary to write the new data to the file? Perhaps you could just append the new data to the existing data frame using rbind. (The write/read combination is going to be slow in comparison).

Even if it is necessary to write the new data, it's probably better to write the new data and use rbind to update the data frame in your app.

library(shiny)

D <- "fielda,fieldb\n1,2\n3,4"
write(D, file = "data.csv")

runApp(
  list(
    ui = fluidPage(
      headerPanel('Title'),
      sidebarPanel(
        textInput("fielda", label="fielda", value=""),
        textInput("fieldb", label="fieldb", value=""),
        actionButton("addButton", "insert data")
      ),
      mainPanel(
        tableOutput("table"))
    ),

    server = function(input, output) {     
      data <- reactiveValues(
        file = read.csv("data.csv", 
                        header=TRUE, 
                        sep=",", 
                        quote="")
      )

      addData <- observeEvent(
        input$addButton,
        {
          newLine <- data.frame(fielda = input$fielda, 
                                fieldb = input$fieldb)

          write.table(newLine, 
                    file = "data.csv", 
                    col.names = FALSE,
                    row.names=FALSE, 
                    quote=FALSE,
                    append = TRUE,
                    sep = ",")
          data$file <- read.csv("data.csv",
                                header=TRUE, 
                                sep=",", 
                                quote="")
        }
      )

      output$table <- 
        renderTable(data$file, include.rownames=FALSE)

    }
  )
)
Benjamin
  • 16,897
  • 6
  • 45
  • 65