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; }