Learn R Programming

linkeR: Effortless Linked Views for 'shiny' Applications

Create synchronized, interactive dashboards where one click updates multiple components

linkeR makes it effortless to create linked views in 'shiny' applications. When users interact with one component (like clicking a map marker), all related components (tables, charts, other maps) automatically update to show corresponding information.

What linkeR Does

  • Bidirectional Linking: Click a map marker → table row highlights. Click table row → map zooms and shows popup.
  • One-Line Setup: Link multiple components with a single function call
  • Custom Behaviors: Define exactly what happens when users click different components
  • Multi-Component Support: Link maps, tables, charts, and more in complex dashboards
  • Zero Boilerplate: No manual observer setup or event handling required

Why Use linkeR?

Before linkeR (Manual Approach)

# Complex manual setup for each component pair
observeEvent(input$map_marker_click, {
  clicked_id <- input$map_marker_click$id
  # Find corresponding table row
  row_idx <- which(my_data()$id == clicked_id)
  # Update table selection
  dataTableProxy("my_table") %>% selectRows(row_idx)
  # Update map view
  leafletProxy("my_map") %>% setView(...)
  # Update any other components...
  # Repeat this for every component combination!
})

observeEvent(input$my_table_rows_selected, {
  # More boilerplate code...
  # Handle edge cases...
  # Ensure consistency...
})

With linkeR (Simple Approach)

# One line links everything!
link_plots(
  session,
  my_map = my_data,
  my_table = my_data,
  shared_id_column = "id"
)

Key Benefits

Manual ApproachlinkeR Approach
50+ lines of observer code1 function call
Easy to introduce bugsTested and reliable
Hard to maintainDeclarative and clear
Limited to 2 componentsUnlimited components
No built-in customizationRich customization options

Installation

# Install from CRAN (when available)
install.packages("linkeR")

# Or install development version from GitHub
# install.packages("devtools")
devtools::install_github("EpiForeSITE/linkeR")

Requirements

For linking to work, your setup needs:

  1. Shared ID Column: All datasets must have a common identifier column
  2. Matching Component IDs:
    • Leaflet: Use layerId = ~your_id_column
    • DT: Row numbers automatically map to data rows
  3. Reactive Data: Wrap your data in reactive()
# Good: Proper setup
my_data <- reactive({
  data.frame(
    id = 1:10,           # ← Shared ID column
    name = paste("Item", 1:10),
    lat = runif(10), lng = runif(10)
  )
})

output$my_map <- renderLeaflet({
  leaflet(my_data()) %>%
    addMarkers(layerId = ~id)  # ← layerId matches shared_id_column
})

link_plots(session, my_map = my_data, shared_id_column = "id")

# Bad: Missing layerId
output$my_map <- renderLeaflet({
  leaflet(my_data()) %>%
    addMarkers()  # ← No layerId = no linking!
})

Supported Components

ComponentStatusNotes
Leaflet Maps✅ Full SupportInteractive maps with markers, circles, polygons
DT DataTables✅ Full SupportSortable, filterable tables
Plotly Charts

Copy Link

Version

Install

install.packages('linkeR')

Version

0.1.2

License

MIT + file LICENSE

Issues

Pull Requests

Stars

Forks

Maintainer

Jake Wagoner

Last Published

September 21st, 2025

Functions in linkeR (0.1.2)

apply_default_leaflet_behavior

Apply Default Leaflet Behavior for Selection Events
register_dt

Register a DT DataTable Component
link_plots

Simple Plot Linking Function for Non-Modular 'shiny' Apps
linkeR-imports

Package imports
process_sf_data

Process SF Data for Leaflet Integration
register_leaflet

Register a Leaflet Component
setup_datatable_observers

Setup DataTable Observers
create_link_registry

Create a Link Registry for 'shiny' Component Coordination
update_dt_selection

Update DT Selection Based on Shared ID
setup_leaflet_observers

Setup Leaflet Map Observers
update_leaflet_selection

Update Leaflet Map Selection
detect_component_type

Detect Component Type Based on Output ID Patterns
setup_component_observers

Set up observers for different component types