앵귤러 template-driven form을 설정하는 방법을 보겠습니다.
먼저, 폼을 사용하기 위해서는 앵귤러 폼 라이브러리에서 forms 모듈을 가져와야 합니다.
//scr/app/app.module.ts
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule // forms module
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
※모듈을 추가를 하지 않으면 아래와 같이 템플릿이나 ts 클래서 파일에서 해당 찾을 수 없습니다.
폼을 사용하고자 하는 템플릿에 아래와 같이 폼을 더합니다.
기본폼부터 시작해서 하나씩 추가하며 보겠습니다. 먼저, 템플릿 폼의 기능을 하나도 추가하지 않은 폼은 아래와 같습니다.
<!-- form.component.html -->
<form>
<div>
<input type="text">
</div>
<div>
<input type="text">
</div>
<div>
<input type="text">
</div>
<button>Submit</button>
</form>
템플릿 폼을 사용하기 위해서는 해당 폼을 forms 모듈과 연결해야 하는데요 연결은 아래와 같이 폼에 템플릿 변수를 생성한 뒤 그 값에 'ngForm'이라는 값을 부여하여 연결합니다.
<!-- form.component.html -->
<form #form="ngForm">
<div>
<input type="text">
</div>
<div>
<input type="text">
</div>
<div>
<input type="text">
</div>
<button>Submit</button>
</form>
해당 폼에 서밋 이벤트를 더해 템플릿 폼 객체를 확인해 보겠습니다. 아래와 같이 서밋 이벤트를 연결하고 매개변수에 폼의 템플릿 변수명을 추가합니다.
<!-- form.component.html -->
<form #form="ngForm" (submit)="onSubmit(form)">
<div>
<input type="text">
</div>
<div>
<input type="text">
</div>
<div>
<input type="text">
</div>
<button>Submit</button>
</form>
그리고 해당 템플릿 클래스에 아래와 같이 해당 function을 매개변수와 함께 추가합니다. 매개변수로 들어오는 값의 타입은 'NgForm'으로 forms 모듈에서 옵니다.
/** form.component.ts */
import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms'; // forms module
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
onSubmit(form: NgForm) {
console.log(form)
}
}
이후 템플릿에서 제출을 클릭하면 아래와 같이 제출된 폼을 확인 가능합니다. 보이는 것처럼 객체 안에는 value, status, errors, touched 등 활용가능한 다양한 속성들이 제공됩니다. controls는 폼에 포함된 각각의 input이라고 생각하면 되는데 지금은 input을 해당 폼의 컨트롤로 연결하는 작업을 하지 않았기 때문에 보시는 것처럼 빈 객체로 표시됩니다.
해당 폼에 컨트롤로 연결하기 위해서는 'name' 속성과 'ngModel' 속성 두 가지 필요한데요. 'name' 속성은 해당 컨트롤의 이름을 지정하여 판별할 수 있게 해 주고 'ngModel' 속성은 폼과 연결하는 기능을 합니다. 둘 중 하나라도 생략되는 컨트롤로 인식되지 않습니다.
<!-- form.component.html -->
<form #form="ngForm" (submit)="onSubmit(form)">
<div>
<input type="text" name="name" ngModel>
</div>
<div>
<input type="text" name="phone" ngModel>
</div>
<div>
<input type="text" name="email" ngModel>
</div>
<button>Submit</button>
</form>
위와 같이 추가 한 뒤 다시 제출해 보면 아래와 같이 연결된 컨트롤을 확인할 수 있습니다.
그럼 제약조건을 추가해 보겠습니다. template-driven 폼은 템플릿에 제약조건을 설정하는데요. 일반적인 html에서 제공하는 제약조건을 추가하는 것과 비슷합니다. 가장 기본적인 'required' 제약조건을 추가해 보겠습니다.
<!-- form.component.html -->
<form #form="ngForm" (submit)="onSubmit(form)">
<div>
<input type="text" name="name" ngModel required>
</div>
<div>
<input type="text" name="phone" ngModel required>
</div>
<div>
<input type="text" name="email" ngModel required>
</div>
<button>Submit</button>
</form>
제약조건을 추가 후 제출하게 되면 아래와 같이 'status'가 'INVALID'라고 뜹니다.
이러한 기능을 활용하여 다양한 구현이 가능한데요 그럼 템플릿 폼을 활용하여 제약조건과 에러 메시지를 포함한 간단한 폼을 만들어 보겠습니다.
<!-- form.component.html -->
<form #form="ngForm" (submit)="onSubmit(form)">
<div>
<input type="text" name="name" ngModel required #name="ngModel">
</div>
<div>
<input type="text" name="phone" ngModel required #phone="ngModel">
</div>
<div>
<input type="text" name="email" ngModel required #email="ngModel">
</div>
<button>Submit</button>
</form>
각 컨트롤의 제약조건에 맞는 에러메시지를 조건과 함께 추가하여 제약조건에 어긋날 때 에러메시지를 표시합니다. 아래에서 'touched'라는 조건을 추가하였는데 이는 에러의 여부만 조건으로 사용하면 최초 필수항목에 값이 없으므로 에러값이 참으로 반환되어 사용자가 입력을 시도하기 전에 메시지가 표시되어 사용자가 불편함을 느낄 수 있기 때문입니다.
<!-- form.component.html -->
<form #form="ngForm" (submit)="onSubmit(form)">
<div>
<input type="text" name="name" ngModel required #name="ngModel">
<div *ngIf="name.touched && name.errors?.['required']">name required</div>
</div>
<div>
<input type="text" name="phone" ngModel required #phone="ngModel">
<div *ngIf="phone.touched && phone.errors?.['required']">phone required</div>
</div>
<div>
<input type="text" name="email" ngModel required #email="ngModel">
<div *ngIf="email.touched && email.errors?.['required']">email required</div>
</div>
<button>Submit</button>
</form>
※에러메시지는 아래와 같이 'invalid'를 사용하여 구현도 가능하나 제약조건이 여러 개인 경우 에러메시지를 구분하여 표현하기 힘들기 때문에 위의 방법을 추천합니다.
<!-- form.component.html -->
<form #form="ngForm" (submit)="onSubmit(form)">
<div>
<input type="text" name="name" ngModel required #name="ngModel">
<div *ngIf="name.touched && name.invalid">name required</div>
</div>
<div>
<input type="text" name="phone" ngModel required #phone="ngModel">
<div *ngIf="phone.touched && phone.invalid">phone required</div>
</div>
<div>
<input type="text" name="email" ngModel required #email="ngModel">
<div *ngIf="email.touched && email.invalid">email required</div>
</div>
<button>Submit</button>
</form>
이후 클래스 파일에서 아래와 같이 폼의 상태를 확인하고 처리하는 코드를 작성 가능합니다.
/** form.component.ts */
import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
onSubmit(form: NgForm) {
if(form.valid) {
console.log(form)
// add an action when form is valid
}
form.resetForm()
}
}
이상으로 앵귤러 폼 - Template-driven form에 대해서 알아보았습니다.
'프론트엔드 > 앵귤러' 카테고리의 다른 글
앵귤러 (Front) - 배포하기 (Netlify) (0) | 2023.01.22 |
---|---|
앵귤러 - Observable (0) | 2023.01.19 |
앵귤러 - 스타일 라이브러리(부트스트랩, 제이쿼리, 폰트어썸) (0) | 2023.01.11 |
앵귤러 템플릿 - Pipes (0) | 2023.01.10 |
앵귤러 템플릿 - Template Reference Variable (0) | 2023.01.10 |