Hey!
I'm not sure if this is intended behaviour, but I think I may have hit an edge case with AccordionTrigger when it's applied via hostDirectives rather than directly on an element. In that setup, clicks on nested children inside the trigger don't seem to toggle the panel (clicking its direct text works fine), whereas using ngAccordionTrigger directly works in all cases.
From what I can tell, it may be related to _findTriggerPattern resolving the target via .closest('[ngAccordionTrigger]') — since host-directive usage doesn't stamp that attribute onto the host element, the lookup appears to fail for nested targets.
Adding an explicit host: { ngAccordionTrigger: '' } seems to fix the problem, but I haven't found any reference to such practice. I believe it would be nice to make it working out of the box.
Cheers!
@Component({
selector: '[myTrigger]',
hostDirectives: [
{
directive: AccordionTrigger,
inputs: ['panel', 'disabled', 'expanded'],
outputs: ['expandedChange'],
},
],
// uncomment to make it working
// host: { ngAccordionTrigger: '' },
template: ` <ng-content /> `,
styles: `
:host {
font-size: 16px;
}
`,
})
export class MyTrigger {}
@Component({
selector: 'CustomAccordion',
imports: [
NgTemplateOutlet,
AccordionGroup,
AccordionTrigger,
AccordionPanel,
AccordionContent,
],
template: `
<div ngAccordionGroup [multiExpandable]="false">
@if (trigger()) {
<ng-container
[ngTemplateOutlet]="trigger()"
[ngTemplateOutletContext]="{
panel: panel,
expanded: expanded(),
expandedChange: () => expanded.update(v=> !v),
disabled: disabled(),
}"
[ngTemplateOutletInjector]="'outlet'" />
} @else {
<button
ngAccordionTrigger
[panel]="panel"
[(expanded)]="expanded">
Click works! ✅
<span>Text inside span: working ✅</span>
</button>
}
<div ngAccordionPanel #panel="ngAccordionPanel">
<ng-template ngAccordionContent>
Content
</ng-template>
</div>
</div>
`,
})
export class CustomAccordion {
readonly disabled = model(false);
readonly expanded = model(false);
readonly trigger = input<TemplateRef<unknown> | undefined>(undefined);
}
@Component({
selector: 'Consumer',
imports: [MyTrigger, CustomAccordion],
template: `
<CustomAccordion />
<hr />
<CustomAccordion [trigger]="customTrigger" />
<ng-template
#customTrigger
let-panel="panel"
let-disabled="disabled"
let-expanded="expanded"
let-expandedChange="expandedChange">
<button
myTrigger
class="trigger"
[panel]="panel"
[disabled]="disabled"
[expanded]="expanded"
(expandedChange)="expandedChange()">
Click works! ✅
<span>Text inside span: not working ❌</span>
</button>
</ng-template>
`,
styles: `
.trigger {
color: red;
}
`,
})
export class Consumer {}
https://stackblitz.com/edit/stackblitz-starters-gpx1tbtc?file=src%2Fmain.ts
Use Case
Custom trigger
Hey!
I'm not sure if this is intended behaviour, but I think I may have hit an edge case with
AccordionTriggerwhen it's applied via hostDirectives rather than directly on an element. In that setup, clicks on nested children inside the trigger don't seem to toggle the panel (clicking its direct text works fine), whereas usingngAccordionTriggerdirectly works in all cases.From what I can tell, it may be related to
_findTriggerPatternresolving the target via.closest('[ngAccordionTrigger]')— since host-directive usage doesn't stamp that attribute onto the host element, the lookup appears to fail for nested targets.Adding an explicit
host: { ngAccordionTrigger: '' }seems to fix the problem, but I haven't found any reference to such practice. I believe it would be nice to make it working out of the box.Cheers!
https://stackblitz.com/edit/stackblitz-starters-gpx1tbtc?file=src%2Fmain.ts
Use Case
Custom trigger