4章:Building Forms Like a Pro
を読んだので調べたことをつらつらと書く
フォーム系
・テンプレート変数
#addExpenseFormはテンプレート変数
Viewchildで参照できる
https://qiita.com/Nkot117/items/21adf2c9828bc03f7ca8
https://www.digitalocean.com/community/tutorials/angular-viewchild-access-component-ja
<form #addExpenseForm="ngForm" (ngSubmit)="onSubmit()">
@ViewChild('addExpenseForm') form!: NgForm;
・FormGroup
これでデータが同期される
<form [formGroup]="addExpenseForm2">
<input formControlName="description" type="text"/>
</form>
addExpenseForm2 = new FormGroup({
description: new FormControl('Test'),
});
・デバック
jsonをかませばとりあえずなんでも出力される
{{expenseToAdd | json}}
・双方向バインディング
<input #description="ngModel" [(ngModel)]="expenseToAdd.description" type="text" id="description" name="description">
@Input() expenseToAdd: AddExpense = {
description: '',
amountExclVat: null,
vatPercentage: null,
date: null,
};
・jsonでフォームにデータを代入するする
export interface AddExpenseReactive {
description?: string;
amount?: {
amountExclVat?: number;
vatPercentage?: number;
};
date?: string[];
tags?: string[];
}
addExpenseForm2 = new FormGroup({
description: new FormControl('Test'),
amount: new FormGroup({
amountExclVat: new FormControl<number | null>(null),
vatPercentage: new FormControl<number | null>(null),
}),
date: new FormControl<string[]>([]),
tags: new FormArray<FormControl<string>>([]),
});
public set addExpense2(value: AddExpenseReactive) {
this.addExpenseForm2.patchValue(value);
}
validation
・デフォルト
maxが100なので100超えるとエラーになる
<input #amount="ngModel" [max]=100 [(ngModel)]="expenseToAdd.amountExclVat" type="number" id="amountExclVat" name="amountExclVat">
{{amount?.errors ?? "noerror" | json}}
touchedをつけると一度でもタッチした後のみエラーになる
maxのときだけ以下のエラーがでる
<span *ngIf="addExpenseForm.touched && amount.hasError('max')">this field is required</span>
・カスタムバリデーター
description: new FormControl('', [
Validators.required,
maxWordCountValidator(3),
]),
export function maxWordCountValidator(maxWords: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const wordCount = control?.value?.trim().split(' ').length;
return wordCount > maxWords ? { maxWordCount: { count: wordCount } } : null;
};
}
エラー
・Can’t bind to ‘formGroup’ since it isn’t a known property of ‘form’.ngtsc(-998002)
ReactiveFormsModuleをimportする
https://stackoverflow.com/questions/39152071/cant-bind-to-formgroup-since-it-isnt-a-known-property-of-form
・ERROR RuntimeError: NG01053: formGroupName must be used with a parent formGroup directive. You’ll want to add a formGroup
ERROR RuntimeError: NG01053: formGroupName must be used with a parent formGroup directive. You’ll want to add a formGroup
directive and pass it an existing FormGroup instance (you can create one in your class).
formにFormGroupを設定し、残りの要素はformのタグの中に入れると解消する
・ERROR Error: Cannot find control with name: ‘0’
trackbyを指定する必要がある
https://kakkoyakakko2.hatenablog.com/entry/2018/12/29/143957
<div class="form-field" *ngFor="let item of tags.controls; index as i;trackBy: trackByIndex">
trackByIndex(index: number, _: any) {
return index;
}