Event Participant List — Reference Implementation
1. Purpose
This page is a reading guide, not a design spec. The Event Participant list at tanstack-event-participant-list.component.ts is the first canonical bake of the project’s list-screen patterns. When building a new list screen — T02 Number Stock, M02 Membership Members, E04 Event Results, future Audit Log, future Affiliations — read the design docs first, then read the EP component side-by-side as the live reference.
The component is ~1,600 lines because it carries every pattern. A purely substrate-driven list screen with no stats strip, no side panel, no chip flags, and no row-summoned modal would be ~400 lines.
2. Reading order
-
Filterable List Pattern — substrate (ColumnConfig, query adapter, widgets) and composition (out-of-band filters, side panel, bulk lifecycle, effects discipline, single navigate). Read fully.
-
List Screen Affordances — visual + interaction spec for the chrome (page header, stats strip, filter chips, utilities row, hover panel, side panel). Read fully.
-
C07 Data Table — the table itself (rows, headers, bulk shell). Skim — relevant when bulk-mode chrome surfaces.
-
E02 Event Participants — the screen spec being implemented. Read fully.
-
The component file below — read in the order suggested in Pattern map below; jump straight to the file:line citations for each pattern you need.
3. Pattern map
The component is structured as one config + one model + one service + one component + three presentational sub-components. The component itself follows a fixed section order via comment banners (/* ----- <name> ----- */). Read these sections:
| Pattern | File | Approximate location | Why read it |
|---|---|---|---|
Column config — single source of truth |
|
Whole file |
One |
Out-of-band filter signals (chip flags + showInactive) |
|
|
Co-located with the substrate types so all filter dimensions are visible together. |
Path-param remap idiom |
|
Bottom of file — |
The seam between Angular’s |
Value-equal derived state signals |
Same file |
|
Without value-equality, every router emit re-fires the fetch effect in a loop. Copy the equality helpers verbatim — they’re not entity-specific. |
Single |
Same file |
Private |
The discipline that keeps |
Row-fetch effect with |
Same file |
|
The canonical effect-discipline bake. Note the |
Stats fetch effect (event-scoped, refetch only on scope change) |
Same file |
Constructor — second effect block |
Stats counts are scope-driven, not filter-driven. Refetch only when the parent id changes. |
Snapshot-fallback signals (side panel + cluster modal) |
Same file |
Constructor — third + fourth effect blocks; |
The pattern that keeps a side panel or row-summoned modal rendered when the row falls off the visible page mid-fetch. |
Side panel via |
Same file |
|
Browser-back closes the panel naturally. The panel component is purely presentational — input: row, output: close. |
Bulk-selection lifecycle |
Same file |
|
Selection cleared on every scope change by the row-fetch effect (single source of truth). Bulk toolbar replaces the action toolbar at ≥2 selected; row-level View action disables while bulk is active. |
Sort header click behaviour |
Same file |
|
~25-line state machine. Copy verbatim. |
Stats strip + chip-flag toggling |
Same file |
Stats-strip |
|
Hover panel anchor pattern |
Same file |
Order-cluster |
The mouseenter/mouseleave region must span both the chip AND the panel; a chip-only listener unmounts the panel mid-read when the cursor crosses into the panel. |
Row-summoned modal (cluster overview) |
Same file |
|
Captures |
Disabled-with-tooltip stub affordances |
Same file |
Action toolbar in the page header — every |
Disabled buttons don’t dispatch hover events on most browsers; the wrapper span is the tooltip surface. Project-wide convention. |
4. Adapting for a new screen
The minimum surface a new list screen needs from this reference:
-
Mirror the column-config / model split. The model module is the home for out-of-band signal types (chip flags, scope toggle keys) and view-model intersections that augment the typed-client DTO.
-
Copy the equality helpers (
stateEqual,sortingEqual,filtersEqual,chipFlagsEqual) and therouteParamReaderadapter verbatim — they’re not entity-specific. -
Adapt the
navigate()method’s foreign-param preservation list to the screen’s URL params (dropviewif no side panel; add the screen’s specific ambient params). -
Decide which patterns the new screen needs:
-
Stats strip → wire chip flags + a stats endpoint (or skip).
-
Side panel → wire
?view=+ snapshot signal pair (or skip; defer to a full-page detail screen). -
Row-summoned modal → wire the
clusterModalEpIdtriple (state signal + snapshot + return-target) (or skip). -
Bulk actions → wire selectedIds + bulk toolbar (or skip — read-only screens don’t need it).
-
Hover panel → wire the anchor wrapper pattern (or skip — most cells don’t need a rich hover).
-
-
Compose the affordances per List Screen Affordances in the template — same vertical band order, same Bootstrap classes.
The presentational sub-components (side panel, hover panel, row-summoned modal) are screen-specific — they consume an entity’s data shape. The list-component patterns above are not.
5. Status
Reference implementation as of US #610 / Feature #608. Future refinements surface upstream in Filterable List Pattern and List Screen Affordances; this page tracks the EP component as the canonical bake until a second list-screen consumer surfaces refinements that justify cross-screen consolidation (then this page either gets companion entries or retires in favour of multi-screen pattern docs).
6. References
-
admin-portal/src/main/webapp/app/event-participants/ - the EP component directory.
-
admin-portal/src/main/webapp/app/shared/filter/ - the mirrored substrate (upstream:
prototypes/filterable-list/). -
design-journal/2026-04/jhipster-filterable-data-table.adoc- substrate evolution + prototype findings