Angular でアコーディオンを実装


背景

Angularで、"「詳しい情報を表示・・・」を押すと、にゅるっとアコーディオンが開く"みたいな機能を実装したく、Animationsを使って実装してみました。
当初、ngx-bootstrapのAccordionModuleを使おうと思ったのですが、イマイチやりたいことができなかったので、こちらの方法をとりました。

前提

@angular/animationsを使用しています。
Angular4以降は設定方法が変わったらしく、導入の際は以下の記事が参考になりました。
Angular2からAngular4に移行してうまく動かなかったところ[Animation]

また、詳細の表示時と非表示にプラスとマイナスのアイコンを出したかったので、Font Awesomeから適当にアイコンとってきてます。なくても問題ないです。

実装

それでは実装箇所です。
ソースコードはこちら

app.module.ts
// import for animations
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  imports: [
    BrowserAnimationsModule,
  ],
})
accordion.html
<!-- アコーディオンを開く閉じるのボタン -->
<div class="pointerCursor" (click)="onAccordion($event)">
  <i [ngClass]="showDetail ? 'fa fa-minus-circle' : 'fa fa-plus-circle'"></i>
      &nbsp;詳しい情報を{{showDetail ? '隠す' : '表示する'}}
</div>

<!-- アコーディオンの中身 -->
<div *ngIf="showDetail" [@accordion]>
    〜アコーディオンで表示したい内容〜
</div>

accordion.component.ts
import { trigger, style, animate, transition } from '@angular/animations';

@Component({
  selector: 'sample-app',
  templateUrl: './accordion.html',
  styleUrls: ['./accordionStyle.scss'],
  animations: [
    trigger('accordion', [
      transition(':enter', [
        style({ height: '0', opacity: 0, overflow: 'hidden' }),
        animate('500ms', style({ height: '*', opacity: 1 }))
      ]),
      transition(':leave', [
        style({ height: '*', opacity: '1', overflow: 'hidden' }),
        animate('500ms', style({ height: '0' }))
      ])
    ])
  ],
})

export class AccordionTest {

  public showDetail: boolean;

  constructor(){
  }

  // アコーディオン開閉時に呼ばれるイベント
  onAccordion($event) {
    this.showDetail = !this.showDetail;
  }
}

クリックできる感を出したかったので、以下のCSSを適用しています。

accordionStyle.scss
// マウスポインターを指マークにする
.pointerCursor {
    cursor: pointer;
}

最後に

こんな感じに仕上がるかと思います。

参考

Angular2からAngular4に移行してうまく動かなかったところ[Animation]
angular 6 animation *ngIf, transition not work
CSSだけでアコーディオンを作る方法