Get Selected Row from Datatable in Shiny App

Get Selected Row From DataTable in Shiny App

UPDATE: you can now access the selected rows using input$tableId_rows_selected in server.R. See here for more details.

To select a unique row, you can change the callback function of your example to this:

callback = "function(table) {
table.on('click.dt', 'tr', function() {
table.$('tr.selected').removeClass('selected');
$(this).toggleClass('selected');
Shiny.onInputChange('rows',
table.rows('.selected').data()[0][0]);
});
}"

When you click on a row,it basically removes any selected rows (they have the .selected class) and selects the row you clicked on.

I also changed the code in the Shiny.onInputChange function so that it returns the number in the first column.

R Shiny : Get data from selected row

Here is a complete example based on the Shiny example you referenced. This uses mpg data from ggplot2.

First, you can create a reactive expression to determine which rows should be filtered and shown in the table. Whenever one of your inputs change, then the reactive expression will be reevaluated. To access the filtered data, you can reference as filtered_rows() (note the parentheses).

To get the selected rows, you can use input$table_rows_selected since your dataTableOutput is called table (just append "_rows_selected"). This can be one or more than one rows, and returns row numbers (e.g., 8 in your example above). Then, to extract your data, you can use filtered_rows()[input$table_rows_selected, c("model", "trans")] which will include model and trans column data for the filtered rows.

The verbatimTextOutput and toString simply show the results for validation and demonstration. You can use the results in another context as well.

library(shiny)
library(DT)
library(ggplot2)

ui <- fluidPage(
titlePanel("Basic DataTable"),

# Create a new Row in the UI for selectInputs
fluidRow(
column(4,
selectInput("man",
"Manufacturer:",
c("All",
unique(as.character(mpg$manufacturer))))
),
column(4,
selectInput("trans",
"Transmission:",
c("All",
unique(as.character(mpg$trans))))
),
column(4,
selectInput("cyl",
"Cylinders:",
c("All",
unique(as.character(mpg$cyl))))
)
),
# Create a new row for the table.
DT::dataTableOutput("table"),
verbatimTextOutput("text")
)

server <- function(input, output) {

# Filter data based on selections
filtered_rows <- reactive({
data <- mpg
if (input$man != "All") {
data <- data[data$manufacturer == input$man,]
}
if (input$cyl != "All") {
data <- data[data$cyl == input$cyl,]
}
if (input$trans != "All") {
data <- data[data$trans == input$trans,]
}
data
})

# Show filtered data in the datatable
output$table <- DT::renderDataTable(DT::datatable({ filtered_rows() }))

# Show selected text
output$text <- renderText({ toString(filtered_rows()[input$table_rows_selected, c("model", "trans")]) })

}

shinyApp(ui, server)

Get selected row value instead of number in shiny using DT

Something like this:

library(shiny)
library(DT)

ui <- basicPage(
mainPanel(DT::dataTableOutput('mytable')),
textOutput("selected")
)

server <- function(input, output,session) {

mydata <- reactive({mtcars})

output$mytable = DT::renderDataTable(
datatable(mydata())
)

selectedRow <- eventReactive(input$mytable_rows_selected,{
row.names(mtcars)[c(input$mytable_rows_selected)]
})

output$selected <- renderText({
selectedRow()
})
}
runApp(list(ui = ui, server = server))

Select specific row of a datatable with a shiny widget

library(shiny)
library(DT)
library(shinyWidgets)

dat <- mtcars[1:6,]

callback <- JS(
"Shiny.addCustomMessageHandler(",
" 'selectRow',",
" function(index) {",
" table.row(index - 1).select();",
" }",
");"
)

ui <- fluidPage(
br(),
DTOutput("dtable"),
br(),
fluidRow(
column(
4,
pickerInput(
"rowname",
label = "Choose a row",
choices = setNames(1:nrow(dat), rownames(dat))
)
),
column(
3,
textOutput("selectedRow")
)
)
)

server <- function(input, output, session) {

output[["dtable"]] <- renderDT({
datatable(
dat,
extensions = "Select",
selection = "none",
callback = callback,
options = list(
columnDefs = list(
list(className = "dt-center", targets = "_all")
),
select = list(style = "single")
)
)
}, server = FALSE)

output[["selectedRow"]] <- renderText({
i <- input[["dtable_rows_selected"]]
paste0(
"Selected row: ",
ifelse(is.null(i), "none", i)
)
})

observeEvent(input[["rowname"]], {
session$sendCustomMessage("selectRow", input[["rowname"]])
})

}

shinyApp(ui, server)

Shiny modules: how to access selected_rows with DT::datatables?

When working with DT:datatable function we can use built-in functionality to learn about selected rows in the UI.

The object: input$my_DT_table_rows_selected contains the index of the selected row where my_DT_table is the ID of the DT::datatable.

However, when working with modules, the name of the table is now different. It has a prefix which is equal to the ID used to call the module's UI function.
So if that ID is my_ID then the table name will become: my_ID-table_name (note the hyphen after the ID).
This can be easily verified using the developer tools in your browser (e.g. inspector in FireFox).
And the associated input object name then becomes (and we need back ticks to prevent R from interpreting the hyphen as a minus sign):

input$`my_ID-table_name_rows_selected`

Here is a very basic example with some additional learning regarding how to pass a reactive object to a module. The reactive object contains the index of the selected line. I need to pass it without parenthesis. Inside of the module_server function I refer to the reactive object with parenthesis.

UI module in ui_module.R

module_ui <- function(id) {
ns <- NS(id) # create namespace

tagList(
fluidRow(column(6, DT::dataTableOutput(ns("dt_table")))),
fluidRow(column(4, verbatimTextOutput(ns("render_selected_line"))))
)
}

Server module in server_module.R

table_server <- function(input, output, session, data) {

output$dt_table <- DT::renderDataTable(
DT::datatable(
data = data,
selection = "single"
)
)
}

selected_line_server <- function(input, output, session, data) {
output$render_selected_line <- renderText({
paste0("My selection was: ", data()) # refer to the reactive object with parenthesis
})

}

Shiny application

library(shiny)
library(dplyr)
library(DT)

source("./modules/ui_module.R")
source("./modules/server_module.R")

ui <- fluidPage(
module_ui("my_ID")
)

server = function(input, output, session) {
data <- mtcars
callModule(table_server, id = "my_ID", data = data) # data is not reactive
callModule(selected_line_server, id = "my_ID", data = selectedLine) # refer to the reactive object selectedLine without parenthesis

selectedLine <- reactive({
req(input$`my_ID-dt_table_rows_selected`)
if (is.null(input$`my_ID-dt_table_rows_selected`)) {
return(NULL)
} else {
rows_selected <- as.numeric(input$`my_ID-dt_table_rows_selected`) # we need to prefix dt_table_rows_selected with the ID of the UI function "my_ID" and a hyphen
}
})

}

shinyApp(ui = ui, server = server)

Select and display the value of a row in Shiny Datatable

A few adjustments:

  1. Your syntax for accessing the selected rows was off slightly. From the data.table documentation, the input is access with the ID passed to the dataTableOutput(); where you wrote input$addr_rows_selected you actually want input$addressTable_rows_selected in order to find the table rendered with DT::dataTableOutput("addressTable").
  2. You are mixing output types with render types. If you want the address to be output as text (per the line textOutput("selectedAddress")) then you should use renderText() rather than DT::renderDataTable().
  3. In order to render the address as text, you must take the address (components) and collapse it down to a character string, which can be done with paste(...,collapse = ",")
library(shiny)
library(data.table)
addr <- as.data.table(read.csv("addresses.csv", header = T, stringsAsFactors = F))
names(addr) [1:4]<- c("STREET ADDRESS","CITY NAME","PROVINCE","POSTAL CODE")

ui <- fluidPage(
br(),
fluidRow(
column(12, div(DT::dataTableOutput("addressTable"), style="font-family:verdana", align="left"))
),
fluidRow(
column(4, div(textOutput("selectedAddress"), align="center"))
)
)

server <- function(input, output) {
output$addressTable <- DT::renderDataTable({addr}, server = T, selection = 'single')

output$selectedAddress <- renderText({
selectedrowindex <- input$addressTable_rows_selected
selectedrowindex <- as.numeric(selectedrowindex)
selectedrow <- paste(addr[selectedrowindex,],collapse = ", ")
selectedrow
})
}

shinyApp(ui, server)


Related Topics



Leave a reply



Submit