-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Description
Which @angular package(s) are relevant/related to the feature request?
@angular/aria
Description
ngAccordionGroup cannot coordinate ngAccordionTrigger directives that live inside child component templates (views). This makes it impossible to build reusable accordion-item components that participate in a shared group defined by a parent.
Current behavior
AccordionGroup discovers triggers via contentChildren(AccordionTrigger, { descendants: true }). Angular's contentChildren only traverses the content DOM; it does not cross into child component view boundaries. Triggers defined inside a child component's own template are invisible to a parent-level ngAccordionGroup.
Interestingly, the reverse direction does work: AccordionTrigger successfully finds its parent group via inject(ACCORDION_GROUP) because DI naturally crosses view boundaries. This creates an asymmetry: triggers know about the group, but the group doesn't know about the triggers.
Reproduction
// panel.component.ts — reusable accordion item
@Component({
selector: 'app-panel',
imports: [AccordionTrigger, AccordionPanel],
template: `
<button ngAccordionTrigger [panel]="panel" #trigger="ngAccordionTrigger">
<ng-content select="[title]" />
</button>
<div ngAccordionPanel #panel="ngAccordionPanel">
<ng-content />
</div>
`,
})
export class PanelComponent {}<!-- parent.component.html -->
<div ngAccordionGroup [multiExpandable]="false">
<app-panel>
<span title>Section 1</span>
<p>Content 1</p>
</app-panel>
<app-panel>
<span title>Section 2</span>
<p>Content 2</p>
</app-panel>
</div>Result: Each trigger injects the group (no DI error), but the group's contentChildren query returns an empty list. The group cannot coordinate expansion (e.g. single-expand mode), and keyboard navigation between triggers does not work.
Workaround: Place a separate ngAccordionGroup inside each child component. This gives each panel its own independent accordion group, but loses all cross-panel coordination (multiExpandable, keyboard navigation between items, expandAll()/collapseAll(), etc.).
Expected behavior
ngAccordionGroup should discover and coordinate ngAccordionTrigger directives regardless of whether they are in the same template or inside child component views.
Use case
Accordion items are commonly wrapped in reusable components: a panel component with a header, icon, animations, and projected content. This is a standard composition pattern:
- A
<app-faq-item>component that encapsulates the trigger + panel + styling - A
<app-collapsible-section>used across different pages - A
<app-settings-panel>with consistent expand/collapse behavior
In all these cases, multiple instances should participate in a shared ngAccordionGroup to get single-expand mode, keyboard navigation, and expandAll()/collapseAll() for free.