## Template-driven forms - 5
---

---
## NgModel
https://angular.io/api/forms/NgModel

---
## NgModel
* 建立FormControl實體
* 追蹤表單輸入或選取值
* 追蹤表單修改狀態與驗證
* 維持表單元件與Model同步
---
#### 直接使用Model進行資料綁定
單向綁定
```typescript=
<input name="account" [ngModel]="account" #account="ngModel"/>
```
雙向綁定
```typescript=
<input name="account" [(ngModel)]="account" #account="ngModel"/>
```
錯誤範例
```typescript=
<input name="account" value="test" [ngModel]="account"/>
```
---
### NgModel exportAs
```typescript=
<input name="account" required [(ngModel)]="account" #account="ngModel"/>
<div *ngIf="account?.errors?.required">
該欄位不能為空
</div>
```

https://angular.io/guide/forms
---
### 內建Validators
https://angular.io/api/forms/Validators
---
### 表單驗證CSS樣式

---
### NgModel Name
* 獨立存在
```typescript=
<input required [(ngModel)]="account" #account="ngModel"/>
```
* 於 `<form>` tag內
```typescript=
<form>
<input name="account" required [(ngModel)]="account" #account="ngModel"/>
</form>
```
---
## ngModelOptions
```typescript=
@Input('ngModelOptions')
options: {
name?: string;
standalone?: boolean;
updateOn?: FormHooks;
}
```
https://angular.io/api/forms/NgModel#using-ngmodel-on-a-standalone-control
---
### ngModelOptions standalone
```typescript=
<form>
<my-person-control ngModel [ngModelOptions]="{standalone: true}">
</my-person-control>
</form>
```
---
### ngModelOptions name
```typescript=
<form>
<my-person-control name="Nancy" ngModel [ngModelOptions]="{name: 'user'}">
</my-person-control>
</form>
<!-- form value: {user: ''} -->
```
---
### NgModel 屬性
https://angular.io/api/forms/NgModel
---
# NgForm
---
## NgForm
* 追蹤群組內Form Control 狀態
* 預設綁定`<form>`
* ExportAs ngForm
---
### NgForm 屬性
https://angular.io/api/forms/NgForm
---
### ngSubmit
```typescript=
<form (ngSubmit)="onSubmit(f)" #f="ngForm">
<input name="username" ngModel/>
<button type="submit">Submit</button>
</form>
```
```typescript=
<form #f="ngForm">
<input name="username" ngModel/>
<button type="button" (click)="onSubmit(f)">Submit</button>
</form>
```
---
<!-- ## NgForm - value
### 取得欄位值的注意事項
* 預設
--- -->
# NgModelGroup
---
## NgModelGroup
* 建立欄位群組
* 只能使用在有`<form>`標籤內
* 建立表單群組`FormGroup`
* 追蹤取得群組內表單控制項的狀態
---
## NgModelGroup屬性
https://angular.io/api/forms/NgModelGroup
---
# Validation
---
## Custom Validators
---
```typescript=
@Directive({
selector: '[appAge]',
providers: [{provide: NG_VALIDATORS, useExisting: AgeValidatorDirective, multi: true}]
})
export class AgeValidatorDirective implements Validator {
@Input('appAge') appAge: number;
validate(control: AbstractControl): {[key: string]: any} | null {
return control.value >= this.appAge ? null : {'ageLimit': true};
}
}
```
```htmlmixed=
<input name="age" appAge="18" ngModel/>
```
---
## Cross Field Validation
---
```typescript=
@Directive({
selector: '[appCompare]',
providers: [{ provide: NG_VALIDATORS, useExisting: CompareDirective, multi: true }]
})
export class CompareDirective implements Validator {
@Input('appCompare') compareControlKey: string;
constructor() { }
validate(control: AbstractControl): { [key: string]: any; } {
const compareControl = control.root.get(this.compareControlKey);
const valid = this.compareControlKey && compareControl.value && control.value === compareControl.value;
return valid ? null : { 'compare': { value: c.value } };
}
}
```
```htmlmixed=
<form>
<input name="password" ngModel required/>
<input name="password2" ngModel required appCompare="password"/>
</form>
```
---
## Custom Async Validator
---
```typescript=
@Directive({
selector: '[appAgeValidator]',
providers: [{provide: NG_ASYNC_VALIDATORS, useExisting: AgeValidatorDirective, multi: true}]
})
export class AgeValidatorDirective implements AsyncValidator{
constructor() { }
validate(control: AbstractControl): Observable<ValidationErrors|null> {
return of({'custom': true});
}
}
```
```htmlmixed=
<form>
<input name="account" type="text" ngModel appAgeValidator #mAccount="ngModel" required>
</form>
```
---
# FormsModule
https://angular.io/api/forms/FormsModule
---
## ControlValueAccessor
https://github.com/angular/angular/blob/master/packages/forms/src/directives/radio_control_value_accessor.ts
---
## 自訂 NG_VALUE_ACCESSOR
https://ithelp.ithome.com.tw/articles/10204510
---
EIP-NG
---
{"metaMigratedAt":"2023-06-15T09:48:16.618Z","metaMigratedFrom":"YAML","title":"Template-driven forms","breaks":true,"description":"2020/06/22 新人課程","contributors":"[{\"id\":\"79a6af84-a897-462e-9bd4-c64e37dcd72b\",\"add\":4709,\"del\":54}]"}