[Angular] Angular Material Bottom Sheet을 이용한 하단 메뉴 만들기

2021. 2. 28. 11:09WEB.DEV/Angular

반응형

이번 포스팅에서는 Angular Material Bottom Sheet을 이용해서 특정한 동작을 했을 때 하단에서 메뉴가 올라오는 하단 메뉴를 만들어보겠습니다.

 

Angular Material

UI component infrastructure and Material Design components for Angular web applications.

material.angular.io

먼저 버튼 모듈인 MatButtonModule과 하단 메뉴를 위한 MatBottomSheetModule 모듈을 추가해주도록 하겠습니다.

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';

import {AppComponent} from './app.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatButtonModule} from '@angular/material/button';
import {MatBottomSheetModule} from '@angular/material/bottom-sheet'


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    MatButtonModule,
    MatBottomSheetModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

먼저 컴포넌트 템플릿에 버튼을 추가해주도록 하겠습니다.

<button 
    mat-button
>
    추가하기
</button>

 그러면 아래와 같이 버튼이 보입니다.

이제 이 버튼을 클릭했을 때 BottomSheet이 열리도록 해보겠습니다. 그러기 전에 먼저 MatBottomSheet의 open 함수를 보게 되면 인수로 컴포넌트와 템플릿을 받도록 되어 있습니다.

먼저 템플릿을 이용해서 만드는 방법을 알아보도록 하겠습니다. 템플릿을 이용하는 방법은 <ng-template>를 이용합니다. 아래와 같이 ng-template을 만들어줍니다.

<ng-template #bottomSheetTemplate>
  <nav>
    <ul>
      <li *ngFor="let snack of snackList">
        <button mat-button>{{snack}}</button>
      </li>
    </ul>
  </nav>
</ng-template>

그 다음에 컴포넌트에서 불러온 후 MatBottomSheet open 함수에 추가를 해주도록 하겠습니다.

...

import {MatBottomSheet} from '@angular/material/bottom-sheet';

@Component({
    ...
});
export class AppComponent implements OnInit {
    @ViewChild('bottomSheetTemplate') bottomSheetTemplate: TemplateRef<any>;
    
    snackList: string[] = [
        '홈런볼',
        '썬칩',
        '콘칩',
        '다이제'
    ];
    
    constructor(
        private bottomSheet: MatBottomSheet
    ) {
    }
    
    ...
    
    openBottomSheet(): void {
        this.bottomSheet.open(bottomSheetTemplate);
    }
}

그리고 아까 추가해놓은 button 클릭 시 openBottomSheet 함수를 호출하도록 해주겠습니다.

<button
    mat-button
    (click)="openBottomSheet()"
>
    추가하기
</button>

그 다음 버튼을 클릭하면 아래와 같이 하단 메뉴가 보이는것을 볼수 있습니다.

추가로 버튼 아래에 추가된 과자 목록을 만들고 하단 메뉴를 클릭했을 때 추가가 되도록 해보겠습니다.

먼저 추가된 과자 목록을 보여주기 위한 배열을 만들어 주고 템플릿에 추가를 해주도록 하겠습니다.

// app.component.ts

...

@Component({
    ...
});
export class AppComponent implements OnInit {
    
    ...
    
    addedSnackList: string[] = [];
    
    ...
    
}
...

<h3>추가된 과자들</h3>
<ul *ngIf="snackList.length > 0; else emptyList">
  <li *ngFor="let snack of addedSnackList">
    {{snack}}
  </li>
</ul>
<ng-template #emptyList>
  <span>추가된 과자가 없습니다.</span>
</ng-template>

 

그럼 이제 추가하기를 클릭했을 때 나오는 하단 메뉴에 있는 버튼을 클릭 했을 때 목록에 추가되도록 해보겠습니다.

...

export class AppComponent implements OnInit {

    ...
    
    addSnack(snack): void {
        this.addedSnackList.push(snack);
    }
}
...

<ng-template #bottomSheetTemplate>
  <nav>
    <ul>
      <li *ngFor="let snack of snackList">
        <button
          mat-button
          (click)="addSnack(snack)"
        >{{snack}}</button>
      </li>
    </ul>
  </nav>
</ng-template>

위와 같이 한 후 하단 메뉴에서 과자를 클릭하면 목록에 과자가 하나씩 추가되는 것을 볼수 있습니다.

만약 여기서 과자가 추가될 때 마다 하단 메뉴가 닫히도록 하기 위해서는 아래와 같이 MatBottomSheet에 dismiss 함수를 호출해주면 됩니다. 그러면 과자를 클릭할 때 마다 하단 메뉴가 닫히는 것을 볼수 있습니다.

    ...
    
    addSnack(snack: string): void {
        this.addedSnackList.push(snack);
        this.bottomSheet.dismiss();
    }
}

이번에는 컴포넌트를 생성해서 추가를 해보도록 하겠습니다. 먼저 Angualr CLI를 이용해서 컴포넌트를 생성해주겠습니다.

$ ng g c bottom-sheet --skip-tests

그리고 bottom-sheet.component.html에 위 템플릿 부분에 있는 nav를 붙여 넣도록 하겠습니다.

<nav>
    <ul>
        <li *ngFor="let snack of snackList">
            <button
                mat-button
                (click)="addSnack(snack)"
            >{{snack}}</button>
        </li>
    </ul>
</nav>

그리고 snackList와 addSnack 함수를 bottom-sheet.component.ts에 추가를 해주도록 하겠습니다.

import {Component, OnInit} from '@angular/core';

@Component({
  selector: 'app-bottom-sheet',
  templateUrl: './bottom-sheet.component.html',
  styleUrls: ['./bottom-sheet.component.scss']
})
export class BottomSheetComponent implements OnInit {
  snackList: string[] = [
    '홈런볼',
    '썬칩',
    '콘칩',
    '다이제'
  ];

  constructor() {
  }

  ngOnInit(): void {
  }

  addSnack(snack: string): void {

  }

}

그 다음 아까 만들어둔 openBottomSheet 안에 open 함수 안의 템플릿을 BottomSheetComponent로 변경을 해주도록 하겠습니다. 그리고 확인을 하면 기존 템플릿을 추가했을 때와 동일하게 보이는 것을 볼수 있습니다.

이제 템플릿에서 과자를 클릭했을 때 추가된 과자 목록에 과자가 추가되도록 해보겠습니다. 그런데 여기서 추가된 과자 목록은 AppComponent에 있고 과자 목록은 BottomSheetComponent에 있습니다. 이때 AppComponent로 클릭한 과자를 MatBottomSheetRef를 이용해서 넘겨주고 AppComponent에서 받도록 하겠습니다.

...

import {MatBottomSheetRef} from '@angular/material/bottom-sheet';

@Component({
  ...
})
export class BottomSheetComponent implements OnInit {
  
  ...
  
  constructor(
    private bottomSheetRef: MatBottomSheetRef<BottomSheetComponent>
  ) {
  }

  ...
  
  addSnack(snack: string): void {
    this.bottomSheetRef.dismiss(snack);
  }

}
...

export class AppComponent implements OnInit {

    ...
    
    openBottomSheet(): void {
        const ref = this.bottomSheet.open(BottomSheetComponent);
        ref.afterDismissed().subscribe(res => {
            this.addedSnackList.push(res);
        });
    }
}

위와 같이 한 후 과자를 클릭을 하면 아래와 같이 과자들이 추가되는 것을 볼수 있습니다.


추가로 MatBottomSheet 옵션 몇가지를 알아보도록 하겠습니다.

  • autoFocus : bottom sheet이 보여질 때 제일 처음 있는 포커스 가능한 요소에 포커스 여부를 설정하는 옵션입니다. true를 하면 포커스가 되고 false를 하면 포커스가 되지 않습니다.
  • backdropClass : bottom sheet이 보일 때 나타나는 overlay의 클래스를 변경하는 옵션입니다.
  • closeOnNavigation : 페이지를 뒤로 / 앞으로 이동을 할 때 bottom sheet 닫힘을 정하는 옵션입니다. true를 하면 이동을 할 때 닫히고 false를 하면 닫히지 않습니다.
  • data : open 인수에 추가한 컴포넌트에 데이터를 전달할 때 사용하는 옵션입니다.
  • direction : bottom sheet 안의 정렬을 정하는 옵션입니다. ltr과 rtl이 있습니다. ltr은 왼쪽에서 오른쪽으로, rtl은 오른쪽에서 왼쪽으로 입니다(기본적으로 ltr이 설정되어 있습니다).
  • disableClose : bottom sheet 밖을 클릭했을 때 닫힘 여부를 설정하는 옵션입니다. true를 하면 bottom sheet 밖을 클릭 했을 때 닫히지 않고 false를 하면 닫힙니다(기본적으로 false가 설정되어 있습니다).
  • hasBackdrop : overlay를 보여줄건지 정하는 옵션입니다. true를 하면 보여지고 false를 하면 안 보입니다.
  • panelClass : bottom sheet이 보여지는 패널의 클래스를 변결할 때 사용하는 옵션입니다.

여기에 나와있지 않는 옵션과 좀 더 자세한 설명은 Material BottomSheet API에서 확인하실수 있습니다.

 

Angular Material

UI component infrastructure and Material Design components for Angular web applications.

material.angular.io

 

부족한 글 읽어주셔서 감사합니다💛

 

728x90
반응형