Javascriptの私のモデル(this.profile
)には、{email, isDefault, status}
の配列であるemails
というプロパティがあります。
それから私はそれを以下のように定義しました
this.profileForm = this.formBuilder.group({
.... other properties here
emails: [this.profile.emails]
});
console.log(this.profile.emails); //is an array
console.log(this.profileForm.emails); // undefined
htmlファイルで私はそれを使用しました
<div *ngFor="let emailInfo of profileForm.emails">
{{emailInfo.email}}
<button (click)="removeEmail(emailInfo)">
Remove
</button>
</div>
formGroup
に追加せず、配列として使用する場合(以下のように)、正常に機能しますが、この配列を空にしないというビジネスルールがあり、フォームを設定できません。この長さに基づく検証
emails : [];
this.profileForm = this.formBuilder.group({
.... other properties here
});
this.emails = this.profile.emails;
console.log(this.profile.emails); //is an array
console.log(this.emails); // is an array
また、formBuilder.array
を使用してみましたが、これはデータの配列ではなく、コントロールの配列を使用するためのものです。
emails: this.formBuilder.array([this.profile.emails])
次に、私の質問は、配列をモデルからUIにバインドする方法と、配列の長さを検証する方法です。
モデルからUIに配列をバインドするにはどうすればよいですか?
さて、私はすべてのメールを_profile.emails
_からformArray
にプッシュしたいと思います。そうしないと、値はありますが、検証はありません。
配列の長さをどのように検証する必要がありますか?
Validators.minLength(Number)
は、他のcontrolと同じように使用できます。
デモコード:
コンポーネント:
_export class AnyComponent implements OnInit {
profileForm: FormGroup;
emailsCtrl: FormArray;
constructor(private formBuilder: FormBuilder) { }
ngOnInit(): void {
this.emailsCtrl = this.formBuilder.array([], Validators.minLength(ANY_NUMBER));
this.profile.emails.forEach((email: any) => this.emailsCtrl.Push(this.initEmail(email)));
this.profileForm = this.formBuilder.group({
// ... other controls
emails: this.emailsCtrl
});
}
private initEmail = (obj: any): FormGroup => {
return this.formBuilder.group({
'email': [obj.email], //, any validation],
'isDefault': [obj.isDefault] //, any validation]
});
}
}
_
テンプレート:
_<div *ngFor="let emailInfo of emailsCtrl.value">
{{emailInfo.email}}
<button (click)="removeEmail(emailInfo)">
Remove
</button>
</div>
<div *ngIf="emailsCtrl.hasError('minlength')">
It should have at least {{emailsCtrl.getError('minlength').requiredLength}} emails
</div>
_
PS1:Validators.minLength(param)
methodのパラメータは1より大きくなければならないことに注意してください、それ以外の場合は検証されません。
ご覧のとおり、 source whencontrolが空の場合、自動的にnullを返します。
次に、期待どおりに機能させるために、required
Validatorを追加できます。
_this.emailsCtrl = this.formBuilder.array([], Validators.compose([Validators.required, Validators.minLength(ANY_NUMBER > 1)]);
_
そしてテンプレートで:
_<div *ngIf="emailsCtrl.invalid">
<span *ngIf="emailsCtrl.hasError('required')">
It's required
</span>
<span *ngIf="emailsCtrl.hasError('minlength')">
It should have at least {{emailsCtrl.getError('minlength').requiredLength}} emails
</span>
</div>
_
PS2:
削除したいメールのインデックスをremoveEmail
関数に渡す方が理にかなっていると思うので、indexOf
specificemail
のインデックスを取得します。あなたはこのようなことをすることができます:
_<div *ngFor="let emailInfo of emailsCtrl.value; let i = index">
{{emailInfo.email}}
<button (click)="removeEmail(i)">
Remove
</button>
</div>
_
コンポーネント:
_removeEmail(i: number): void {
this.emailsCtrl.removeAt(i);
}
_
このシンプルなものを見てください DEMO
これは私にとってはうまくいきます(角度2.1.2)。このアプローチにより、電子メールのカスタム検証を柔軟に定義できます。
this.profileForm = this.formBuilder.group({
emails: [this.profile.emails, FormValidatorUtils.nonEmpty]
// ......
});
export class FormValidatorUtils {
static nonEmpty(control: any) {
if (!control.value || control.value.length === 0) {
return { 'noElements': true };
}
return null;
}
}