Skip to content
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

Improve edit functionality #493

Closed
mgirlich opened this issue Jan 30, 2018 · 9 comments · May be fixed by #509
Closed

Improve edit functionality #493

mgirlich opened this issue Jan 30, 2018 · 9 comments · May be fixed by #509
Milestone

Comments

@mgirlich
Copy link
Contributor

mgirlich commented Jan 30, 2018

Unfortunately, I hit the wrong button and deleted the old content here instead of only updating the code...

Below is an example for a fast edit ability without the need of a double click. In some cases this could be more useful than the current edit function.

library(shiny)
library(purrr)
library(glue)
library(dplyr)

shinyApp(
  ui = fluidPage(
    DT::dataTableOutput("x1"),
    
    # javascript for making sure to display correct value
    tags$script(
      paste0(
        "Shiny.addCustomMessageHandler('update',
          function(message) {
            document.getElementById(message.id).value = message.value;
          }
        );"
      )
    )
  ),
  
  server = function(input, output, session) {
    data <- reactiveValues(
      table = tibble(
        # unique_row_identifier can be a unique character or number
        unique_row_identifier = paste0("row_number_", 1:10e3),
        value_to_modify = sample(0:10, 10e3, replace = TRUE)
      )
    )
    
    # update the data in R
    observeEvent(input$input_change, {
      row <- input$input_change$id == data$table$unique_row_identifier
      data$table$value_to_modify[row] <- input$input_change$value
    })
    
    output$x1 <- DT::renderDataTable(
      {
        # isolate input data so that an update doesn't cause a rerendering
        isolate(data$table) %>% 
          # render a number input
          mutate(input = glue::glue(
            # the id of the input element is needed to be able to render the correct value (see javascript code above)
            "<input id='input_{unique_row_identifier}' type='number' \\
            min='0' max='5' step='1' \\
            value='{value_to_modify}' \\
            style='width: 100%' \\
            onchange='Shiny.onInputChange(\"input_change\", {{id: \"{unique_row_identifier}\", value: this.value}})'/>"
            # the quotes in id: \"{unique_row_identifier}\" are only needed if unique_row_identifier is a character
          ))
      },
      escape = 1,
      options = list(stateSave = TRUE) # necessary for displaying the correct values in the input column
    )
    
    # call script to display correct values
    observeEvent(input$x1_state, {
      rows <- input$x1_rows_current
      ids <- glue::glue("input_{data$table$unique_row_identifier[rows]}")
      vals <- data$table$value_to_modify[rows]
      
      purrr::walk2(
        ids, vals,
        ~ session$sendCustomMessage("update", list(id = .x, value = .y))
      )
    })
  }
)
@yihui
Copy link
Member

yihui commented Jan 30, 2018

These are fantastic suggestions and also good challenges! But I'm afraid I'll have to defer the work to a future contributor like @shrektan :)

@shrektan
Copy link
Collaborator

Thanks for the suggestion. The whole point is to make the table editing easier and for this goal we need to take inspirations from other table libraries like rhandsontable~

It seems like a good challenge. I'll think about it~~ 🐌

@vikram-rawat
Copy link

Please, could you add functionality to edit or delete a perticular row from DT? There are many users who would love to have a CRUD operation of Databases through shiny. DT is nicest of all the interface for this reason. Something like this.

https://community.rstudio.com/t/building-crud-with-shiny/2881/9

@tellyshia
Copy link

@mgirlich Thank you for the code. I was looking for the same functionalities. Your code works for me but I don't know how to obtain the updated values. Using your example, how can i get the updated "x1$input"?

@mgirlich
Copy link
Contributor Author

mgirlich commented Apr 5, 2018

@tellyshia The value and row just updated is saved in input$input_change. The whole current table is saved in data$table.

To see this in action I recommend using an extra browser() in the observer to input$input_change as in the following code:

observeEvent(input$input_change, {
      browser()
      row <- input$input_change$id
      data$table$input[row] <- input$input_change$value
    })

I hope this helps you.

@tellyshia
Copy link

tellyshia commented Apr 13, 2018

@mgirlich Thanks. I realized the reason why it didn't work for me was because I used characters instead of numbers in input_{row}. Do I really need to have row number in my table for this to work? What if my column has unique variable names like the table below??

Actually it would help the readers to understand your example better if the column names are not so generic, e.g. "row" and "input".

Hope to see your reply. Thanks in advance. :)

 data <- reactiveValues(
      table = tibble(
        row = LETTERS[1:20],
        input = sample(0:10, 1:20, replace = TRUE)
      )
    )

@mgirlich
Copy link
Contributor Author

I edited my example to make it better understandable. This should hopefully make it clear to you.

@tellyshia
Copy link

Thank you for your generosity. If I may extend your example more, how can I add another shiny input column next to it. For example, a checkbox for TRUE/FALSE. I am not sure how to modify the part on #call script to display correct values.

data <- reactiveValues(
      table = tibble(
        # unique_row_identifier can be a unique character or number
        unique_row_identifier = paste0("row_number_", 1:10e3),
        value_to_modify = sample(0:10, 10e3, replace = TRUE),
        logic = TRUE, 
      )
    )

@yihui yihui closed this as completed in 3bf27fe Apr 4, 2019
@yihui yihui added this to the v0.6 milestone Apr 4, 2019
@yihui
Copy link
Member

yihui commented Apr 4, 2019

With the current dev version of DT, you can bulk edit rows, columns, or the whole table:

image

Please check out the changelog and see if it fits your purpose: https://github.com/rstudio/DT/blob/master/NEWS.md#changes-in-dt-version-06 Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants