Skip to content

Commit 224bd6f

Browse files
committed
refactor(aria/accordion): Replace ContentChildren with manual registration of triggers
1 parent d215bfb commit 224bd6f

5 files changed

Lines changed: 45 additions & 8 deletions

File tree

goldens/aria/accordion/index.api.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ export class AccordionGroup {
2525
expandAll(): void;
2626
readonly multiExpandable: _angular_core.InputSignalWithTransform<boolean, unknown>;
2727
readonly _pattern: AccordionGroupPattern;
28+
_registerTrigger(trigger: AccordionTrigger): void;
2829
readonly softDisabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
2930
readonly textDirection: _angular_core.WritableSignal<_angular_cdk_bidi.Direction>;
31+
_unregisterTrigger(trigger: AccordionTrigger): void;
3032
readonly wrap: _angular_core.InputSignalWithTransform<boolean, unknown>;
3133
// (undocumented)
32-
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<AccordionGroup, "[ngAccordionGroup]", ["ngAccordionGroup"], { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "multiExpandable": { "alias": "multiExpandable"; "required": false; "isSignal": true; }; "softDisabled": { "alias": "softDisabled"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; }, {}, ["_triggers"], never, true, never>;
34+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<AccordionGroup, "[ngAccordionGroup]", ["ngAccordionGroup"], { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "multiExpandable": { "alias": "multiExpandable"; "required": false; "isSignal": true; }; "softDisabled": { "alias": "softDisabled"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
3335
// (undocumented)
3436
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AccordionGroup, never>;
3537
}
@@ -51,22 +53,25 @@ export class AccordionPanel {
5153
}
5254

5355
// @public
54-
export class AccordionTrigger implements OnInit {
56+
export class AccordionTrigger implements OnInit, OnDestroy {
5557
readonly active: _angular_core.Signal<boolean>;
5658
collapse(): void;
5759
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
5860
readonly element: HTMLElement;
5961
expand(): void;
6062
readonly expanded: _angular_core.ModelSignal<boolean>;
6163
readonly id: _angular_core.InputSignal<string>;
64+
readonly index: _angular_core.InputSignal<number | undefined>;
65+
// (undocumented)
66+
ngOnDestroy(): void;
6267
// (undocumented)
6368
ngOnInit(): void;
6469
readonly panel: _angular_core.InputSignal<AccordionPanel>;
6570
readonly panelId: _angular_core.Signal<string>;
6671
_pattern: AccordionTriggerPattern;
6772
toggle(): void;
6873
// (undocumented)
69-
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<AccordionTrigger, "[ngAccordionTrigger]", ["ngAccordionTrigger"], { "panel": { "alias": "panel"; "required": true; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "expanded": { "alias": "expanded"; "required": false; "isSignal": true; }; }, { "expanded": "expandedChange"; }, never, never, true, never>;
74+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<AccordionTrigger, "[ngAccordionTrigger]", ["ngAccordionTrigger"], { "panel": { "alias": "panel"; "required": true; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "index": { "alias": "index"; "required": false; "isSignal": true; }; "expanded": { "alias": "expanded"; "required": false; "isSignal": true; }; }, { "expanded": "expandedChange"; }, never, never, true, never>;
7075
// (undocumented)
7176
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AccordionTrigger, never>;
7277
}

src/aria/accordion/accordion-group.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
ElementRef,
1212
booleanAttribute,
1313
computed,
14-
contentChildren,
1514
inject,
1615
input,
1716
signal,
@@ -75,10 +74,17 @@ export class AccordionGroup {
7574
readonly element = this._elementRef.nativeElement as HTMLElement;
7675

7776
/** The AccordionTriggers nested inside this group. */
78-
private readonly _triggers = contentChildren(AccordionTrigger, {descendants: true});
77+
private readonly _triggers = signal(new Set<AccordionTrigger>());
78+
79+
/** The AccordionTriggers nested inside this group. */
80+
private readonly _sortedTriggers = computed(() => {
81+
return [...this._triggers()].sort((a, b) => a.index()! - b.index()!);
82+
});
7983

8084
/** The corresponding patterns for the accordion triggers. */
81-
private readonly _triggerPatterns = computed(() => this._triggers().map(t => t._pattern));
85+
private readonly _triggerPatterns = computed(() => {
86+
return this._sortedTriggers().map(t => t._pattern);
87+
});
8288

8389
/** The text direction (ltr or rtl). */
8490
readonly textDirection = inject(Directionality).valueSignal;
@@ -117,4 +123,16 @@ export class AccordionGroup {
117123
collapseAll() {
118124
this._pattern.collapseAll();
119125
}
126+
127+
/** Internal method to register each trigger as we can not use contentChildren. */
128+
_registerTrigger(trigger: AccordionTrigger) {
129+
this._triggers().add(trigger);
130+
this._triggers.set(new Set(this._triggers()));
131+
}
132+
133+
/** Internal method to unregister each trigger as we can not use contentChildren. */
134+
_unregisterTrigger(trigger: AccordionTrigger) {
135+
this._triggers().delete(trigger);
136+
this._triggers.set(new Set(this._triggers()));
137+
}
120138
}

src/aria/accordion/accordion-trigger.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import {
1010
Directive,
1111
ElementRef,
12+
OnDestroy,
1213
OnInit,
1314
booleanAttribute,
1415
computed,
@@ -53,7 +54,7 @@ import {AccordionPanel} from './accordion-panel';
5354
'[attr.tabindex]': '_pattern.tabIndex()',
5455
},
5556
})
56-
export class AccordionTrigger implements OnInit {
57+
export class AccordionTrigger implements OnInit, OnDestroy {
5758
/** A reference to the trigger element. */
5859
private readonly _elementRef = inject(ElementRef);
5960

@@ -69,12 +70,15 @@ export class AccordionTrigger implements OnInit {
6970
/** The unique identifier for the trigger. */
7071
readonly id = input(inject(_IdGenerator).getId('ng-accordion-trigger-', true));
7172

72-
/** The unique identifier for the correspondingtrigger panel. */
73+
/** The unique identifier for the corresponding trigger panel. */
7374
readonly panelId = computed(() => this.panel().id());
7475

7576
/** Whether the trigger is disabled. */
7677
readonly disabled = input(false, {transform: booleanAttribute});
7778

79+
/** The index of the trigger within the accordion group. */
80+
readonly index = input<number>();
81+
7882
/** Whether the corresponding panel is expanded. */
7983
readonly expanded = model<boolean>(false);
8084

@@ -93,6 +97,14 @@ export class AccordionTrigger implements OnInit {
9397
});
9498

9599
this.panel()._pattern = this._pattern;
100+
101+
this._accordionGroup._registerTrigger(this);
102+
}
103+
104+
ngOnDestroy() {
105+
this.panel()._pattern = undefined;
106+
107+
this._accordionGroup._unregisterTrigger(this);
96108
}
97109

98110
/** Expands this item. */

src/aria/accordion/accordion.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ describe('AccordionGroup', () => {
454454
<div class="item-container">
455455
<button
456456
ngAccordionTrigger
457+
[index]="$index"
457458
[panel]="panel"
458459
[disabled]="item.disabled()"
459460
[(expanded)]="item.expanded"

src/components-examples/aria/accordion/accordion-configurable/accordion-configurable-example.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ <h3 class="example-accordion-header">
1919
<button ngAccordionTrigger
2020
#trigger="ngAccordionTrigger"
2121
class="example-accordion-trigger"
22+
[index]="$index"
2223
[disabled]="item.disabled()"
2324
[(expanded)]="item.expanded"
2425
[panel]="panel">

0 commit comments

Comments
 (0)