ReactiveFormsModule
app.module.ts
또는 FormCotrol
을 사용할 컴포넌트의 .module.ts
에 ReactiveFormsModule
추가app.module.ts
에 추가하였다.import {ReactiveFormsModule} from '@angular/forms';
...
@NgModule({
...
imports: [
...
// other imports ...
ReactiveFormsModule,
],
...
})
export class AppModule {}
FormControl
을 가진 컴포넌트 생성FormControl
의 생성자를 사용하여 초기 값(여기서는 빈 문자열)을 설정name-editor.component.ts
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'app-name-editor',
templateUrl: './name-editor.component.html',
styleUrls: ['./name-editor.component.css'],
})
export class NameEditorComponent {
name = new FormControl('');
...
}
ReactiveFormsModule
에 포함된 FormControlDirective
에서 제공하는 formControl
바인딩을 사용하여 템플릿에서 폼 컨트롤을 업데이트<label for="name">Name: </label>
<input id="name" type="text" [formControl]="name">
<p>Value: {{ name.value }}</p>
setValue()
메서드를 사용하여 값 변경 가능setValue()
는 개별 컨트롤에 대한 새 값을 설정한다. 후술 할 FormGroup
에서 사용할 경우 엄격하게 폼 그룹의 구조를 준수하여야 한다. updateName() {
this.name.setValue('Nancy');
}
동적으로 생성되는 Form Field를 관리하거나, Form의 어려 컨트롤을 논리적으로 그룹화하고 관리해야할 때 Form을 그룹화할 수 있다.
FormGroup
인스턴스로 설정FormGroup
을 초기화하기 위해 이름과 FormControl 이 매핑된 객체를 생성자에 제공src/app/profile-editor/profile-editor.component.ts
import {Component} from '@angular/core';
import {FormGroup, FormControl} from '@angular/forms';
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css'],
})
export class ProfileEditorComponent {
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
...
});
...
}
src/app/profile-editor/profile-editor.component.html
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<label for="first-name">First Name: </label>
<input id="first-name" type="text" formControlName="firstName">
<label for="last-name">Last Name: </label>
<input id="last-name" type="text" formControlName="lastName">
...
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
</form>
onSubmit() {
const formValue = this.profileForm.getRawValue();
console.log(this.profileForm.formValue );
}
FormGroup
인스턴스를 사용하면 대형 FormGroup을 더 작고 관리하기 쉬운 단위로 나눌 수 있다.FormGroup
은 FormControl
인스턴스와 FormGroup
인스턴스를 모두 자식으로 받을 수 있다.src/app/profile-editor/profile-editor.component.ts
import {Component} from '@angular/core';
import {FormGroup, FormControl} from '@angular/forms';
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css'],
})
export class ProfileEditorComponent {
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl(''),
}),
});
...
}
formGroupName
바인딩을 사용하여 템플릿에서 폼 그룹을 연결한다.src/app/profile-editor/profile-editor.component.html
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
...
<div formGroupName="address">
<h2>Address</h2>
<label for="street">Street: </label>
<input id="street" type="text" formControlName="street">
<label for="city">City: </label>
<input id="city" type="text" formControlName="city">
<label for="state">State: </label>
<input id="state" type="text" formControlName="state">
<label for="zip">Zip Code: </label>
<input id="zip" type="text" formControlName="zip">
</div>
</form>
patchValue()
메서드를 사용하면 폼 컨트롤 데이터 모델의 특정 부분만 업데이트 가능하다.src/app/profile-editor/profile-editor.component.ts
updateProfile() {
this.profileForm.patchValue({
firstName: 'Nancy',
address: {
street: '123 Drew Street',
},
});
}
FormArray
클래스 import 및 FormArray Control 정의src/app/profile-editor/profile-editor.component.ts
import {Component} from '@angular/core';
import {FormArray, FormGroup, FormControl} from '@angular/forms';
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css'],
})
export class ProfileEditorComponent {
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl(''),
}),
histories: new FormArray([]),
});
...
}
get histories() {
return this.profileForm.get('histories') as FormArray;
}
add() {
this.histories.push(
new FormGroup({
name: new FormControl('', { validators: [Validators.required] }),
description: new FormControl('', { validators: [Validators.required] }),
})
);
}
remove(index: number) {
this.histories.removeAt(index);
}
formArrayName
바인딩을 사용하여 템플릿에서 FormArray
연결formGroup
바인딩을 사용하여 FormArray
내 FormGroup
연결<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
...
<div formArrayName="histories">
@for (control of form.controls.histories.controls; track idx ; let idx = $index) {
<form [formGroup]="control">
<label for="name">Name: </label>
<input id="name" type="text" formControlName="name">
<label for="description">Description: </label>
<input id="description" type="text" formControlName="description">
<button (click)="add()">추가</button>
<button (click)="remove(idx)">삭제</button>
</form>
</div>
</form>
// form 페칭
setForm(data) {
this.form.patchValue({
...data,
histories: [],
});
data.histories.map((history) => {
const histories = this.form.get('histories') as FormArray;
histories.push(
new FormGroup({
title: new FormControl(history.title, [Validators.required]),
active: new FormControl(history.active, [Validators.required]),
})
);
});
}
References