ReactiveFormsModule 을 활용한 바인딩
사진처럼 N개를 그릴 데이터를 group으로 묶은뒤에 배열로 처리할 것입니다.
이해를 위해서 single이라는 배열이 아닌 단순한 대상을 1개 추가하였습니다.
기존 소스코드를 변경해 보겠습니다.
dashboard.component.ts
import {Component, OnInit} from '@angular/core';
import {FormArray, FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
declare type MyType = {
text: any;
number: any;
};
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit{
builder: FormBuilder;
rows: FormArray;
formGrp: FormGroup;
single: FormControl;
constructor(fb: FormBuilder) { //FormBuilder를 주입받습니다.
this.builder = fb;
this.rows = this.builder.array([]); //주입받은 FormBuilder를 통해서 배열 형태로 값을 담을 변수 생성
this.single = new FormControl('Title', Validators.required); //1개의 데이터에 바인딩할 대상
this.formGrp = this.builder.group({'row_data':this.rows, 'single_data': this.single});
}
ngOnInit():void {
for (let i = 0; i < 10; i++) {
let group = this.builder.group({ //배열에 담을 그룹을 생성
text : this.builder.control('abcd'+i, Validators.minLength(5)), //control함수는 FormControl을 만드는 역할을 합니다.
number: this.builder.control(i, Validators.required)
});
this.rows.push(group);
}
}
showData(arg?: any) { //화면에서 데이터를 볼 함수
if (arg) {
console.log(arg);
} else {
console.log(this.formGrp);
}
}
}
생성자
생성자(contructor)에서, 매개변수로 fb를 받으며, FormBuilder타입을 받습니다.
app모듈에서 ReactiveFormsBuilder를 imports 해 주었기 때문에 생성자에 fb라는 FormsBuilder 값을 받을 수 있는 모습입니다.
FormBuilder를 받으려면 생성자를 통해 가능합니다.
변수 선언부
FormBuilder는 Builder(만들다)의 역할을 해 줍니다.
FormBuilder를 통해서 rows 변수에 FormArray타입의 객체를 만들었습니다.
변수 single은 FormContorl타입이며, input type태그 1개를 만들어 적용할 예정입니다.
formGrp 변수는 FormGroup타입으로 rows와 single변수를 담을 최상위 노드입니다.
FormGroup은 json형식으로 key와value를 갖습니다.
→ FormGroup에 ‘row_data’를 key값으로 주면 rows 변수를 반환
하고, ‘single_data’를 key값으로 주면 single 변수를 반환
하게 됩니다.
ngOnInit
rows변수는 FormArray의 형태이며, 데이터를 넣어주기 위해 group이라는 변수 선언후 builder.group
함수를 호출하여 내용을 채운뒤 대입했습니다.
builder.group
부분은 new FormGroup과 동일한 기능을 가지며, key와 value형태로 값을 채워주었습니다.
key는 일반문자(text, number)가, value에는 FormControl객체가 담겨져 있습니다.
그리고 group을 rows배열에 push해 주었습니다.
html변경
dashboard.component.html
<form [formGroup] = 'formGrp'>
<input type='text' [value]='' formControlName='single_data' />
<div formArrayName="row_data" *ngFor="let item of rows.controls; let i = index;">
<div [formGroupName]="i"> <!-- formArray의 그룹 index값을 추가하여 item의 값을 찾을수 있도록 하여 줍니다. -->
<span>{{i+1}}</span>
<input type='text' formControlName="text" [value] = 'item.value.text' />
<input type='number' formControlName="number" [value] = 'item.value.number'/>
<input type='button' value='보기' (click)='showData(item)' />
</div>
</div>
</form>
<input type='button' value='전부 보기' (click)='showData()' />
먼저 formGroup디렉티브
값에 formGrp
값을 주었습니다.
formControlName
은 선언한 변수 값이 아니라 변수 formGrp의 key값인 single_data가 쓰엿으며, 이는 value값인 single 변수값을 반환하게 됩니다.
컴포넌트에서 선언한 FormArray형태를 가지는 rows는 formGrp에서 선언한 key값인 row_data가 사용되었습니다.
ngFor디렉티브
에서 let i = index부분이 추가 되었는데, 해당 부분은 반복문이 증가하는 index 값을 가져올 수 있습니다.
formGroupName
에 대괄호와 인덱스를 사용한 이유는 따로 key값을 부여하지 않았기 때문에 인덱스로 값을 찾은 후 매핑하기 위함입니다.
참고
https://lts0606.tistory.com/362