-
Notifications
You must be signed in to change notification settings - Fork 182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make it possible to edit values in table #480
Conversation
…atic table on an HTML page without Shiny
Hi, I have a question on this feature. Let's say I have some other analysis that depends on the data in the table. How do link those analysis with the updated data from the edited datatable? For example, if I changed one cell in the table, will the analysis be updated automatically? I have a example code below (not working)
So in this case, I wanted the text output "text" to be automatically updated when I change cell [1,1]. However the code above did not work, what is your thought on this? Thanks! |
@tamluong Your output$text <- renderText({
input$x1_cell_edit
x[1, 1]
}) Note you don't need |
@yihui Thank you! That works perfectly. One thing I noticed is that although y is an reactive expression based on x, y is not automatically updated when x is changed. Was that because Shiny does not recognize x as an input value? |
@tamluong That is because although server <- function(input, output, session) {
x = iris
y <- reactive({
input$x1_cell_edit
x
})
x$Date = Sys.time() + seq_len(nrow(x))
output$x1 = DT::renderDataTable(x, selection = 'none', editable = TRUE)
proxy = dataTableProxy('x1')
observeEvent(input$x1_cell_edit, {
info = input$x1_cell_edit
str(info)
i = info$row
j = info$col
v = info$value
x[i, j] <<- DT::coerceValue(v, x[i, j])
replaceData(proxy, x, resetPaging = FALSE) # important
})
output$text <- renderText({
y()[1, 1]
})
} Or make server <- function(input, output, session) {
x = iris
y <- function() x
x$Date = Sys.time() + seq_len(nrow(x))
output$x1 = DT::renderDataTable(x, selection = 'none', editable = TRUE)
proxy = dataTableProxy('x1')
observeEvent(input$x1_cell_edit, {
info = input$x1_cell_edit
str(info)
i = info$row
j = info$col
v = info$value
x[i, j] <<- DT::coerceValue(v, x[i, j])
replaceData(proxy, x, resetPaging = FALSE) # important
})
output$text <- renderText({
input$x1_cell_edit
y()[1, 1]
})
} |
@yihui that makes perfect sense! Thanks so much! |
Hello! |
The coerceValue command is giving me the following error, since according to the docs it only works with integer, double, date, time and factor values:
The data that i want the user to edit are character values. Any suggestions for a workaround would be immensely appreciated! |
devtools::install_github('rstudio/DT') |
Is there any update on KaterinaKou' s question ? |
@adiguzelomer No: #550. |
@adiguzelomer
|
Thank you for this functionality @yihui of this merged branch :) Is there functionality to From part (4), I've done this little code for SQL database, (only for update). (SQL Server Windows from ODBC Linux)
|
@philibe Currently it is not straightforward, and it may require deeper understanding of the implementation of server-side processing in this package. I did think about wider support for SQL long time ago (see #194), but haven't found time to actually do the work. It will definitely be amazing if all basic SQL operations can be supported in DT (in particular, querying/filtering should be much much faster). Your example is a very good start. |
👍 :) |
@KaterinaKou thank you alot ! I am gonna try it. |
is there a way to use the all the extensions that DT have a long with the editing. ie. fixed columns, hiding columns etc. As far as I can tell and test there is only if I try to use an expression to calculate the data and return datatable with the extensions, the editing is ignored , and viceversa |
Hi! Is there any way that editable= TRUE for specific columns and not for the whole datatable? |
how to write/save the file after making changes to it? |
Hi @yihui , |
Hi @yihui, |
For this example, how would you replicate it, if the datatable itself was based on a reactive value. Let's say we just binded iris and input$test as a dataframe. Where selectInput("test",choices=c(TRUE,FALSE), so it's just a binary choice and the last column of Iris is an editable column that's initial values are based on an input? Obviously a more complicated example wouldn't just spit out the input but I am trying to understand how you can use editable DT as well as the values from it to persist when the underlying data is dependent on inputs. |
Hi @KaterinaKou, this worked for you? I tried to replicate your solution but what I see is that the "user" still could click and edit a cell that is not in the column 3, and when doing "enter" the new value stays in the table. Only when trying to edit column 3, the other values previously changed return to their original value. This is really weird for the user. Maybe I'm doing something wrong. Did you get a solution where the user can't double click and edit the cell? |
For those who want to disable editing on certain columns, I just pushed an implementation through 832714f. Thanks! BTW, you can also see Table 10 in the example https://yihui.shinyapps.io/DT-edit/ |
Hello:) As @rajkumarmaniraja57 already asked, is there a way how I can change a value in a data table that can be filtered based on inputs. So is filtering and editing possible at the same time? |
@PeterDieter No, that is currently not possible. Sorry. |
Is it still "important" to run The example seems to work just fine without If it can be safely avoided, it makes it easier to use a proxy in a shiny module (no need to pass the global session to the proxy). library(shiny)
library(DT)
shinyApp(
ui = fluidPage(
DTOutput('x1')
),
server = function(input, output, session) {
x = iris
x$Date = Sys.time() + seq_len(nrow(x))
output$x1 = renderDT(x, selection = 'none', editable = TRUE)
proxy = dataTableProxy('x1')
observeEvent(input$x1_cell_edit, {
info = input$x1_cell_edit
str(info)
i = info$row
j = info$col
v = info$value
x[i, j] <<- DT::coerceValue(v, x[i, j])
# Code works just fine without the line below
# replaceData(proxy, x, resetPaging = FALSE) # important
})
}
) |
@antoine-sachet Without |
Hi, this is great! Everything works except that after the data are saved, the table displaying the information goes blank and DT says No Matching Records Found, however, if I reload the page, the saved data is there.
|
This functionality is great. In my case, I have a small problem regarding the characters ">" and "<". When using client-side processing example, I cannot change the content of a cell from "setosa" to "< LD", for example, because that means the contents are no longer visible (I know this example doesn't make much sense, but trust me, it's important for my app). This of course happens because "<" and ">" are reserved HTML characters (if I write "< LD" the cell contents are shown as intended). I've noticed that this does not happen when using the example provided for server-side processing. But in that case I have other problems, since my file is provided by the user... Would it be possible to have the server side functionality even in the case of a file uploaded by the user (using I attempted some code based on the above example (pasted below) and failed, with the following error message:
Here is my code: library(shiny)
library(DT)
shinyApp(
ui = fluidPage(
fileInput(
inputId = "upload",
label = span(icon("upload"), "Choose csv file:"),
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
DTOutput('x1')
),
server = function(input, output, session) {
upfile <- reactive({
req(input$upload)
tryCatch({
out <- read.csv(input$upload$datapath, as.is = TRUE)
out$Date <- Sys.time() + seq_len(nrow(out))
}, # return a safeError if a parsing error occurs
error = function(e) stop(safeError(e))
)
return(out)
})
output$x1 = renderDT(upfile(), selection = 'none',
server = TRUE, editable = TRUE)
proxy = dataTableProxy('x1')
observeEvent(input$x1_cell_edit, {
info = input$x1_cell_edit
str(info)
i = info$row
j = info$col
v = info$value
# Here I basically changed x with upfile() in all instances:
upfile()[[j]][i] <<- DT::coerceValue(v, upfile()[[j]][i])
replaceData(proxy, upfile(), resetPaging = FALSE) # important
})
}
) The file used for my tests was created with: write.csv(iris, "iris.csv", row.names = FALSE) Thanks for your work and your time! |
Please open a new issue if you need help or encounter bugs. Leaving comments on a closed PR will be easily missed because it’s difficult to find the entry later. |
Closes #28
Test
Double click in a table cell to edit its value.
(1) client-side processing (static HTML application)
(2) client-side processing in Shiny
(3) server-side processing
(4) server-side processing (without row names)