I checked the Angular documentation and some tutorials but have not resolved my problem.
I have a child component accordeon used in many others. In accordeon, it receives a boolean value from the component using it, to know when it must be opened or closed. Accordeon is also divided between two ng-content, one getting the title given by the parent component, the other getting the content of the parent component.
Here the HTML of accordeon:
<div class="d-flex jc-between ai-center p-s" (click)="toggleAccordeon();" [ngClass]="specialAccordeon ? 'accordeon' : 'special-accordeon'">
<ng-content select="[slot=title]"></ng-content>
<span class="icon-chevron_bottom" [ngClass]="accordeonOpened ? 'rotation_180' : ''"></span>
</div>
<ng-content [@openCloseAccordeon]=animateAccordeon select="[slot=content]" [ngStyle]="accordeonOpened && {'display': 'none'}"></ng-content>
The .ts file of accordeon:
import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core';
import { state, style, transition, animate, trigger } from '@angular/animations';
@Component({
selector: 'srp-accordeon',
templateUrl: './accordeon.component.html',
styleUrls: ['./accordeon.component.scss'],
animations: [
trigger('openCloseAccordeon', [
state('initial', style({
display: 'none',
})),
state('final', style({
display: 'block',
})),
transition('initial => final', [
animate('1s')
]),
transition('final => initial', [
animate('2s')
]),
]),
]
})
export class AccordeonComponent implements OnInit {
accordeonOpened = false;
animateAccordeon = 'initial';
@Output() open: EventEmitter<any> = new EventEmitter();
@Output() close: EventEmitter<any> = new EventEmitter();
@Output() openAccordeon: EventEmitter<any> = new EventEmitter();
@Output() closeAccordeon: EventEmitter<any> = new EventEmitter();
@Input() specialAccordeon;
public toggleAccordeon(): void {
this.animateAccordeon = this.animateAccordeon === 'initial' ? 'final' : 'initial';
this.accordeonOpened = !this.accordeonOpened;
if (this.accordeonOpened) {
this.open.emit(true);
} else {
this.close.emit(false);
}
if (this.animateAccordeon === 'initial') {
this.closeAccordeon.emit('initial');
} else {
this.openAccordeon.emit('final');
}
}
constructor() { }
ngOnInit() {
}
}
The parent component using it, order-delivery, the interesting HTML part:
Currently I manage opening and closing with a ng-class, putting [@openCloseAccordeon]=animateAccordeon doesn't work.
<srp-accordeon [specialAccordeon]="true" (close)="accordeonOpened = false" (open)="accordeonOpened = true" (closeAccordeon)="animateAccordeon = 'initial'" (openAccordeon)="animateAccordeon = 'final'">
<ng-container slot="title">{{currentOrder.statusLabel}} {{(!currentOrder.isCanceled ? currentOrder.isDeliveryAtHome ? 'order.atHome' : 'order.inWithdrawalPoint' : string.Empty) | translate}}</ng-container>
<ng-container slot="content">
<div class="order-delivery__details mb-s" [ngClass]="accordeonOpened ? 'accordeon-opened' : 'accordeon-closed'">
To sum up. I need to get the animation to trigger when the user click on the . I think I miss something, a data to pass to the accordeon component from order-delivery, but don't get what.
Thank you for your help.
Eventually I find how to make it work.
accordeon.html:
accordeon.ts:
No need to specify something in the parent component. One think to remember, the animation can't trigger on ng-content, this is why I added a div wrapping it.