Andi Maier
Andi Maier

Reputation: 1034

Shiny - Change column names in DT table for storing as reactiveVal

I have a Shiny app with a DT datatable in which I can change the column names via Javascript (thanks to another Stackoverflow entry). I would like to store the changed column names in a reactiveVal. However, this does currently not work.

Here is the current code which I use:

library(shiny)
library(DT)

callback <- c(
  "table.on('dblclick.dt', 'thead th', function(e) {",
  "  var $th = $(this);",
  "  var index = $th.index();",
  "  var colname = $th.text(), newcolname = colname;",
  "  var $input = $('<input type=\"text\">')",
  "  $input.val(colname);",
  "  $th.empty().append($input);",
  "  $input.on('change', function(){",
  "    newcolname = $input.val();",
  "    if(newcolname != colname){",
  "      $(table.column(index).header()).text(newcolname);  ",
  "      Shiny.onInputChange('newColumnValue', newcolname);",
  "      console.log( newcolname);",
  "    }",
  "    $input.remove();",
  "  }).on('blur', function(){",
  "    $(table.column(index).header()).text(newcolname);",
  "    $input.remove();",
  "  });",
  "});"
 )

 ui <- fluidPage(
   textOutput("value"),
   tags$head(
   tags$link(rel = "stylesheet", href = "https://cdnjs.cloudflare.com/ajax/libs/jquery-   contextmenu/2.8.0/jquery.contextMenu.min.css"),
   tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.8.0/jquery.contextMenu.min.js")
  ),
  DT::dataTableOutput("table")

)

server <- function(input, output){
  val <- reactiveVal(NULL) 

  mydata <- reactive({
    browser()
    data <- datatable(iris[1:3,], callback = JS(callback))
    val(colnames(data$x$data))
    data
  })

  output$table <- DT::renderDataTable({
    mydata()
  }, server = FALSE) 

  output$value <- renderText({
    val()                     
    })
 }

 shinyApp(ui, server)

However, I do not get any change in my reactiveVal variable. What do I need to change?

Cheers, Andi

Upvotes: 1

Views: 656

Answers (1)

St&#233;phane Laurent
St&#233;phane Laurent

Reputation: 84519

library(shiny)
library(DT)

callback <- c(
  "var colnames = table.columns().header().to$().map(function(){return this.innerHTML;}).get();",
  "Shiny.onInputChange('colnames', colnames);",
  "table.on('dblclick.dt', 'thead th', function(e) {",
  "  var $th = $(this);",
  "  var index = $th.index();",
  "  var colname = $th.text(), newcolname = colname;",
  "  var $input = $('<input type=\"text\">')",
  "  $input.val(colname);",
  "  $th.empty().append($input);",
  "  $input.on('change', function(){",
  "    newcolname = $input.val();",
  "    if(newcolname != colname){",
  "      $(table.column(index).header()).text(newcolname);",
  "      colnames[index] = newcolname;",
  "      Shiny.onInputChange('colnames', colnames);",
  "    }",
  "    $input.remove();",
  "  }).on('blur', function(){",
  "    $(table.column(index).header()).text(newcolname);",
  "    $input.remove();",
  "  });",
  "});"
)

ui <- fluidPage(
  verbatimTextOutput("colnames"),
  DTOutput("table")
)

server <- function(input, output){

  output$table <- renderDT({
    datatable(iris[1:3,], callback = JS(callback), 
              options = list(ordering = FALSE))
  }, server = FALSE) 

  output$colnames <- renderPrint({
    input$colnames                     
  })
}

shinyApp(ui, server)

Upvotes: 1

Related Questions