이번에는 Material Dialog를 추가해보겠습니다.
Dialog는 아래와 같이 동작합니다.
Dialog 동작화면
부모창이 어두워집니다. (dimmed)
모달(modal) 창이 뜨고 입력한 값이 부모로 전달되죠.
Material의 장점은 역시 미리 구현된 동작입니다.
- 모달(modal)과 부모 컴포넌트간 데이터 전달
- 모달(modal) 이외 영역 클릭시 닫기
- ESC로 창닫기
- 웹접근성 고려(자동 포커스)
(창을 닫고 아이콘이 포커스 되는 그 부분)
그럼 코드로 살펴보겠습니다.
1. Import MatDialogModule
app module에 MatDialogModule을 추가합니다.
@angular/material 모듈에 포함되어있습니다.
import { MatDialogModule } from '@angular/material';
...
@NgModule({
...
imports: [
...
MatDialogModule,
...
],
...
})
export class AppModule { }
2. Dialog Component 생성
Dialog에 구성될 화면을 만듭니다.
저는 컴포넌트를 따로 분리하였습니다.
컴포넌트 생성은 굉장히 쉽죠?
(ng g c '이름' Angular 새로 Component 만들기)
Dialog는 부모 컴포넌트로 data를 전달합니다.
MatDialogRef 라는 의존성을 주입합니다.
(여기서 설명했었죠? Angular Service 만들기)
import { Component } from '@angular/core';
import { MatDialogRef } from '@angular/material'
...
@Component({
selector: 'app-consumption',
templateUrl: './consumption.component.html',
styleUrls: ['./consumption.component.css']
})
export class ConsumptionComponent {
constructor(private dialogRef: MatDialogRef) { }
...
onCancel(){
this.dialogRef.close();
}
onSave(){
const returnData = {
amount: this.consumptionForm.controls.amount.value,
desc: this.consumptionForm.controls.desc.value
}
this.dialogRef.close(returnData)
}
}
cancel 버튼과 save 버튼에 이벤트를 연결했죠.
dialogRef의 close 메서드에 data를 전달합니다.
화면 Template은 생략하겠습니다.
그저 Form 컨트롤일뿐.
(Angular Forms)
3. Dialog Component Factory에 등록
그럼 생성해준 Dialog는 동적으로 만들어집니다.
이런 컴포넌트들은 다른 설정이 필요해요.
app module에 entryComponents 라는 것이죠.
...
@NgModule({
...
entryComponents: [
ConsumptionComponent
],
...
})
export class AppModule { }
위와 같은 설정으로 Dialog를 그릴 수 있게됩니다.
Component Factory에 추가가 되기 때문이죠.
4. Dialog 표출
부모 컴포넌트에서 Dialog를 보여주면 됩니다.
아래와 같이 가능합니다.
import { MatDialog } from '@angular/material';
import { ConsumptionComponent } from '../consumption/consumption.component';
...
@Component({
...
})
export class BudgetComponent implements OnInit {
...
constructor(public store: Store, public dialog: MatDialog) { }
...
onAdd() {
const dialogRef = this.dialog.open(ConsumptionComponent, {
width: '250px'
});
dialogRef.afterClosed().subscribe(result => {
if (result) {
let amount: number = Number(result.amount);
let desc: string = result.desc;
this.addConsumption(new Consumption(amount, desc));
}
});
}
...
}
MatDialog 의존성 주입이 되었구요.
(여기서 설명했었죠? Angular Service 만들기)
MatDialog의 메서드를 호출해주면 됩니다.
open이라는 메서드입니다.
dialog에 사용할 컴포넌트와 정보를 넣었죠.
width이외에 data도 전달할 수 있습니다.
open 메서드는 dialogRef를 리턴합니다.
dialogRef를 이용해 닫혔을 때 동작을 정의합니다.
observer 패턴이에요.
result라는 객체로 dialog에서 전달한 값을 받습니다.
조금 복잡하지만 크게 수고를 덜 수 있습니다.
물론 디자인을 변경하려면....
나중에 필요해지면 해보도록 하죠.
전체 소스는 아래 링크에서 볼 수 있습니다.
https://github.com/jsrho1023/account-book