Created
April 9, 2022 07:08
-
-
Save nanxstats/2f79e09060657e143b19d068bd6d79b8 to your computer and use it in GitHub Desktop.
Paginated news list with DT/DataTables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Generate mock data ----------------------------------------------------------- | |
set.seed(42) | |
k <- 100 | |
df <- data.frame( | |
title = unlist(purrr::map2( | |
.x = stringr::word(stringi::stri_rand_lipsum(k), start = 1, end = 10), | |
.y = rep("#", k), | |
.f = function(.x, .y) as.character(htmltools::tags$a(.x, href = .y)) | |
)), | |
time = as.POSIXct(unlist( | |
charlatan::ch_date_time(n = k) | |
), origin = "1970-01-01 00:00.00 UTC"), | |
inst = sample(charlatan::ch_company(n = 20), size = k, replace = TRUE), | |
type = sample( | |
c("backgrounders", "media advisories", "news releases", "readouts", "speeches"), | |
size = k, replace = TRUE | |
), | |
desc = stringi::stri_rand_lipsum(k), | |
stringsAsFactors = FALSE | |
) | |
df$metadata <- paste(df$time, df$inst, df$type, sep = " | ") | |
df <- df[, c("title", "time", "inst", "type", "metadata", "desc")] | |
df <- df[order(df$time, decreasing = TRUE), ] | |
# Create filter widgets using crosstalk ---------------------------------------- | |
df_shared <- crosstalk::SharedData$new(df) | |
ui_filters <- list( | |
crosstalk::filter_select( | |
id = "selector-type", | |
label = "News type", | |
sharedData = df_shared, | |
group = ~type | |
), | |
crosstalk::filter_select( | |
id = "selector-inst", | |
label = "Institution", | |
sharedData = df_shared, | |
group = ~inst | |
) | |
) | |
# Create table widget using DT ------------------------------------------------- | |
ui_dt <- DT::datatable( | |
df_shared, | |
options = list( | |
columnDefs = list(list(visible = FALSE, targets = c(1, 2, 3))), | |
dom = "<'top'fil>rt<'bottom'p><'clear'>", | |
language = list(search = "Filter items:"), | |
pageLength = 3, | |
headerCallback = DT::JS( | |
"function(thead, data, start, end, display){", | |
" $(thead).remove();", | |
"}" | |
) | |
), | |
class = c("table", "table-striped", "table-hover", "table-borderless"), | |
style = "bootstrap4", | |
rownames = FALSE, | |
escape = FALSE, | |
width = "850px", | |
selection = "none" | |
) | |
# Define custom CSS styles for table elements ---------------------------------- | |
css_dt <- textConnection(" | |
table td { display: block; } | |
table td:nth-child(1) { font-size: 1.375rem; } | |
table td:nth-child(2) { color: #555; } | |
div.dataTables_wrapper div.dataTables_filter { display: inline; text-align: left; } | |
div.dataTables_wrapper div.dataTables_filter label { font-weight: 700; } | |
div.dataTables_wrapper div.dataTables_info { display: inline; margin-left: 1ch; padding-top: 0; } | |
div.dataTables_wrapper div.dataTables_length { display: inline; margin-left: 1ch; padding-left: 1ch; border-left: 1px solid;} | |
div.dataTables_wrapper div.dataTables_length label { font-weight: 700; } | |
div.dataTables_wrapper div.dataTables_paginate ul.pagination { justify-content: center; } | |
") | |
# Compose widgets into an HTML page -------------------------------------------- | |
card <- function(title, ...) { | |
htmltools::tags$div( | |
class = "card", | |
htmltools::tags$div(class = "card-header", title), | |
htmltools::tags$div(class = "card-body", ...) | |
) | |
} | |
html <- shiny::fluidPage( | |
title = "DT News List Example", | |
theme = bslib::bs_theme(version = 5, primary = "#295376"), | |
lang = "en", | |
shiny::includeCSS(css_dt), | |
shiny::fluidRow( | |
shiny::column( | |
width = 10, offset = 1, | |
shiny::fluidRow( | |
shiny::column( | |
width = 3, | |
card( | |
title = "Filter news", | |
htmltools::tags$p( | |
"Use filters to search for the most recent news articles." | |
), | |
ui_filters | |
) | |
), | |
shiny::column( | |
width = 9, | |
ui_dt | |
) | |
) | |
) | |
) | |
) | |
htmltools::browsable(html) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment