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.
- 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
# 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...
})
# One line links everything!
link_plots(
session,
my_map = my_data,
my_table = my_data,
shared_id_column = "id"
)
Manual Approach | linkeR Approach |
---|---|
50+ lines of observer code | 1 function call |
Easy to introduce bugs | Tested and reliable |
Hard to maintain | Declarative and clear |
Limited to 2 components | Unlimited components |
No built-in customization | Rich customization options |
# Install from CRAN (when available)
install.packages("linkeR")
# Or install development version from GitHub
# install.packages("devtools")
devtools::install_github("EpiForeSITE/linkeR")
For linking to work, your setup needs:
- Shared ID Column: All datasets must have a common identifier column
- Matching Component IDs:
- Leaflet: Use
layerId = ~your_id_column
- DT: Row numbers automatically map to data rows
- Leaflet: Use
- 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!
})
Component | Status | Notes |
---|---|---|
Leaflet Maps | ✅ Full Support | Interactive maps with markers, circles, polygons |
DT DataTables | ✅ Full Support | Sortable, filterable tables |
Plotly Charts | 🔄 Partial | Requires manual event handling |
Custom Components | 🔄 Partial | Any Shiny component with click events, Requires manual event handling |
Base R Plots | 📋 Planned | Static plots with click detection |
Mapbox | 📋 Planned | Alternative mapping solution |
Contributions are welcome and encouraged! Follow best practice for github contributions.
# Clone and setup
git clone https://github.com/EpiForeSITE/linkeR.git
cd linkeR
# Install dependencies
devtools::install_deps()
# Run tests
devtools::test()
# Check package
devtools::check()
This project is licensed under the MIT License - see the LICENSE file for details.