[Reactive Forms] FormArray 구현을 자식 구성 요소로 잘라냅니다.
11650 단어 AngularTypeScript
마지막으로 한 일
지난번은 아래의 기사에서, 동적으로 추가 & 삭제할 수 있는 폼을 단일의 컴퍼넌트 안에서 구현했습니다.
마지막 기사
[Reactive Forms] FormArray에서 동적으로 추가 삭제할 수 있는 입력 양식 구현
폼을 구현할 때, 복수의 입력란이 필요한 경우가 대부분으로 단일의 컴퍼넌트에 넣으면 가독성이 내려 버립니다. 이번에는 FormArray의 구현 부분을 자식 컴포넌트로 잘라내고 싶습니다.
고민한 곳
여기가 마지막 템플릿입니다.
app.component.html<h3>フォーム</h3>
<form [formGroup]="form">
<div>名前: <input type="text" formControlName="userName"></div>
<div>
<p>スキル情報</p>
<div formArrayName="userSkills">
<div *ngFor="let skill of userSkills.controls; let i = index">
<div [formGroupName]="i">
<div>スキル名: <input type="text" formControlName="skillName"></div>
<div>レベル: <input type="number" formControlName="skillLevel"></div>
<button (click)="removeUserSkill(i)">削除</button>
</div>
</div>
</div>
<button (click)="addUserSkills()">スキルを追加</button>
</div>
</form>
나는 어떤 계층의 부분에서 잘라내면 좋을까? 조금 고민했습니다.
일단의 결론으로서는 FormGroup
를 아이 컴퍼넌트에 건네주어, FormArray 의 부분을 둥글게 잘라내면 잘 구현할 수 있는 것은 아닐까? 라는 결론에 이르렀습니다.
샘플 소스
여기에서는 SkillForm
라는 컴퍼넌트를 새롭게 작성해, 여기에 처리를 잘라 갑니다.
자식 구성 요소 구현
결론부터 쓰면 다음과 같은 컴포넌트의 구현이 됩니다.
skill-form-component.tsimport {Component, Input, OnInit} from '@angular/core';
import {FormArray, FormBuilder, FormGroup} from '@angular/forms';
@Component({
selector: 'app-skill-form',
templateUrl: './skill-form.component.html',
styleUrls: ['./skill-form.component.scss']
})
export class SkillFormComponent implements OnInit {
@Input() parentForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit() {
}
get userSkillForm(): FormGroup {
return this.fb.group({
skillName: [''],
skillLevel: [''],
});
}
get userSkills(): FormArray {
return this.parentForm.get('userSkills') as FormArray;
}
addUserSkills() {
this.userSkills.push(this.userSkillForm);
}
removeUserSkill(index: number) {
this.userSkills.removeAt(index);
}
}
거의 그대로 이식하고 있습니다만, 포인트는 @Input() parentForm: FormGroup;
로 부모 컴퍼넌트의 FormGroup 에 바인딩하고 있는 점입니다.
하위 템플릿 구현
skill-form-component.html<ng-container [formGroup]="parentForm">
<div>
<p>スキル情報</p>
<div formArrayName="userSkills">
<div *ngFor="let skill of userSkills.controls; let i = index">
<div [formGroupName]="i">
<div>スキル名: <input type="text" formControlName="skillName"></div>
<div>レベル: <input type="number" formControlName="skillLevel"></div>
<button (click)="removeUserSkill(i)">削除</button>
</div>
</div>
</div>
<button (click)="addUserSkills()">スキルを追加</button>
</div>
</ng-container>
FormArray의 기술전에, 부모 컴퍼넌트와 동기한 FormGroup를 정의해 주는 것으로, 예상대로의 거동이 됩니다.
상위 템플릿 구현
app.component.html <form [formGroup]="form">
<div>名前: <input type="text" formControlName="userName"></div>
<app-skill-form [parentForm]="form"></app-skill-form>
</form>
부모 템플릿에서 호출 할 때 자식 구성 요소의 FormGroup에 자신의 FormGroup을 전달합니다.
결과적으로 다음과 같이 부모 컴포넌트가 하위 컴포넌트에서 Form 변경을 캡처하고 있음을 알 수 있습니다.
FormGroup이 아니라 FormArray를 바인딩 할 수 없습니까?
할 수 있을지도 모릅니다만, 공식적으로도 기술이 보이지 않았기 때문에 파악할 수 없습니다.
원래 FormArray는 [FormGroup]
가 정의된 가운데, FormArrayName
를 선언하고 이용하기 위해 FormGroup이 있다고 전제일까 추측했습니다.
요약
FormArray에 한정되지 않지만, 아이 컴퍼넌트에 리액티브 폼의 내용을 잘라낼 때에는, 부모의 FormGroup를 바인딩해 주면 잘 구현할 수 있을 것 같습니다.
부모 컴퍼넌트에서는 최종적으로 제출되는 데이터의 취급에 집중할 수 있으므로, 책무를 분리한 구현이 가능합니다.
잘못된 점이 있으면, 지적 부탁드립니다.
참고문헌
여기가 마지막 템플릿입니다.
app.component.html
<h3>フォーム</h3>
<form [formGroup]="form">
<div>名前: <input type="text" formControlName="userName"></div>
<div>
<p>スキル情報</p>
<div formArrayName="userSkills">
<div *ngFor="let skill of userSkills.controls; let i = index">
<div [formGroupName]="i">
<div>スキル名: <input type="text" formControlName="skillName"></div>
<div>レベル: <input type="number" formControlName="skillLevel"></div>
<button (click)="removeUserSkill(i)">削除</button>
</div>
</div>
</div>
<button (click)="addUserSkills()">スキルを追加</button>
</div>
</form>
나는 어떤 계층의 부분에서 잘라내면 좋을까? 조금 고민했습니다.
일단의 결론으로서는
FormGroup
를 아이 컴퍼넌트에 건네주어, FormArray 의 부분을 둥글게 잘라내면 잘 구현할 수 있는 것은 아닐까? 라는 결론에 이르렀습니다.샘플 소스
여기에서는 SkillForm
라는 컴퍼넌트를 새롭게 작성해, 여기에 처리를 잘라 갑니다.
자식 구성 요소 구현
결론부터 쓰면 다음과 같은 컴포넌트의 구현이 됩니다.
skill-form-component.tsimport {Component, Input, OnInit} from '@angular/core';
import {FormArray, FormBuilder, FormGroup} from '@angular/forms';
@Component({
selector: 'app-skill-form',
templateUrl: './skill-form.component.html',
styleUrls: ['./skill-form.component.scss']
})
export class SkillFormComponent implements OnInit {
@Input() parentForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit() {
}
get userSkillForm(): FormGroup {
return this.fb.group({
skillName: [''],
skillLevel: [''],
});
}
get userSkills(): FormArray {
return this.parentForm.get('userSkills') as FormArray;
}
addUserSkills() {
this.userSkills.push(this.userSkillForm);
}
removeUserSkill(index: number) {
this.userSkills.removeAt(index);
}
}
거의 그대로 이식하고 있습니다만, 포인트는 @Input() parentForm: FormGroup;
로 부모 컴퍼넌트의 FormGroup 에 바인딩하고 있는 점입니다.
하위 템플릿 구현
skill-form-component.html<ng-container [formGroup]="parentForm">
<div>
<p>スキル情報</p>
<div formArrayName="userSkills">
<div *ngFor="let skill of userSkills.controls; let i = index">
<div [formGroupName]="i">
<div>スキル名: <input type="text" formControlName="skillName"></div>
<div>レベル: <input type="number" formControlName="skillLevel"></div>
<button (click)="removeUserSkill(i)">削除</button>
</div>
</div>
</div>
<button (click)="addUserSkills()">スキルを追加</button>
</div>
</ng-container>
FormArray의 기술전에, 부모 컴퍼넌트와 동기한 FormGroup를 정의해 주는 것으로, 예상대로의 거동이 됩니다.
상위 템플릿 구현
app.component.html <form [formGroup]="form">
<div>名前: <input type="text" formControlName="userName"></div>
<app-skill-form [parentForm]="form"></app-skill-form>
</form>
부모 템플릿에서 호출 할 때 자식 구성 요소의 FormGroup에 자신의 FormGroup을 전달합니다.
결과적으로 다음과 같이 부모 컴포넌트가 하위 컴포넌트에서 Form 변경을 캡처하고 있음을 알 수 있습니다.
FormGroup이 아니라 FormArray를 바인딩 할 수 없습니까?
할 수 있을지도 모릅니다만, 공식적으로도 기술이 보이지 않았기 때문에 파악할 수 없습니다.
원래 FormArray는 [FormGroup]
가 정의된 가운데, FormArrayName
를 선언하고 이용하기 위해 FormGroup이 있다고 전제일까 추측했습니다.
요약
FormArray에 한정되지 않지만, 아이 컴퍼넌트에 리액티브 폼의 내용을 잘라낼 때에는, 부모의 FormGroup를 바인딩해 주면 잘 구현할 수 있을 것 같습니다.
부모 컴퍼넌트에서는 최종적으로 제출되는 데이터의 취급에 집중할 수 있으므로, 책무를 분리한 구현이 가능합니다.
잘못된 점이 있으면, 지적 부탁드립니다.
참고문헌
import {Component, Input, OnInit} from '@angular/core';
import {FormArray, FormBuilder, FormGroup} from '@angular/forms';
@Component({
selector: 'app-skill-form',
templateUrl: './skill-form.component.html',
styleUrls: ['./skill-form.component.scss']
})
export class SkillFormComponent implements OnInit {
@Input() parentForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit() {
}
get userSkillForm(): FormGroup {
return this.fb.group({
skillName: [''],
skillLevel: [''],
});
}
get userSkills(): FormArray {
return this.parentForm.get('userSkills') as FormArray;
}
addUserSkills() {
this.userSkills.push(this.userSkillForm);
}
removeUserSkill(index: number) {
this.userSkills.removeAt(index);
}
}
<ng-container [formGroup]="parentForm">
<div>
<p>スキル情報</p>
<div formArrayName="userSkills">
<div *ngFor="let skill of userSkills.controls; let i = index">
<div [formGroupName]="i">
<div>スキル名: <input type="text" formControlName="skillName"></div>
<div>レベル: <input type="number" formControlName="skillLevel"></div>
<button (click)="removeUserSkill(i)">削除</button>
</div>
</div>
</div>
<button (click)="addUserSkills()">スキルを追加</button>
</div>
</ng-container>
<form [formGroup]="form">
<div>名前: <input type="text" formControlName="userName"></div>
<app-skill-form [parentForm]="form"></app-skill-form>
</form>
할 수 있을지도 모릅니다만, 공식적으로도 기술이 보이지 않았기 때문에 파악할 수 없습니다.
원래 FormArray는
[FormGroup]
가 정의된 가운데, FormArrayName
를 선언하고 이용하기 위해 FormGroup이 있다고 전제일까 추측했습니다.요약
FormArray에 한정되지 않지만, 아이 컴퍼넌트에 리액티브 폼의 내용을 잘라낼 때에는, 부모의 FormGroup를 바인딩해 주면 잘 구현할 수 있을 것 같습니다.
부모 컴퍼넌트에서는 최종적으로 제출되는 데이터의 취급에 집중할 수 있으므로, 책무를 분리한 구현이 가능합니다.
잘못된 점이 있으면, 지적 부탁드립니다.
참고문헌
Reference
이 문제에 관하여([Reactive Forms] FormArray 구현을 자식 구성 요소로 잘라냅니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/mashman/items/698d2c281df6f2372446텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)