[上課筆記] Angular Forms - template-driven forms

  • 628
  • 0
  • 2019-12-29

Angular Forms
for template-driven forms
非常好的入門課程 重點只放在template-driven forms 
會用到
Rxjs
https://putsreq.com/
如果不太懂的話 可以先看 
Angular: Getting Started
會有Angular 各方面都有講到一點  

app.module.ts
import { FormsModule } from '@angular/forms';
imports:  FormsModule
加入 FormsModule

用CLI 產生 ng g c user-settings-form

app.component.html 移除內容 加上 <app-user-settings-form></app-user-settings-form>

npm install --save bootstrap

angular.json 加入  "styles": "node_modules/bootstrap/dist/css/bootstrap.min.css"

要重開ng serve 才會吃到 新的 styles

卡關記錄  一直沒有bootstrap樣式
因為 我放到 test 那層去了 請放到 architect > build > options > styles 才是正確路徑
補充 要改port 放在 architect  > serve > options > "port": 4500

放到github git remote add origin "Clone with HTTPS 的網址"

https://angular.tw/api/forms/NgForm

Using NgForm
<form #form="ngForm"> 最下面加上 {{form | json}} 可以看到form的資訊

NgModel
input 加上 ngModel 後 {{form.value | json}} 會有變化 => 要有 name 才會有改變

Creating a Data Model
建立 interface UserSettings 這樣就可以在 設定時 用Ctrl+空白鍵 得到提示
export interface UserSettings {
    name: string,
    emailOffers: boolean,
}
userSettings:UserSettings ={
    name: 'Milton',
    emailOffers: true
}

Two-way Data Binding
input 改成 [(ngModel)] = "userSettings.name" 這樣變成雙向綁定
{{userSettings | json}} 會變成 頁面一載入 就會有值 修改內容值也會改變

Copying Form Data
紀錄原本資料 可以用 userSettings : UserSettings = { ...this.originalUserSettings }; 
3個點是淺複製 要深複製需要另外處理(Lodash)
{{originalUserSettings | json}} 觀察改變input內容 這裡就不會變了

HTML5 Field Validation
預設關掉 加上 <form #form="ngForm" ngNativeValidate> 可以打開
HTML5驗證範例 <input id="name" name="name" class="form-control" [(ngModel)] = "userSettings.name" required pattern="B.*" minlength="3" maxlength="4" />

CSS Classes for Validation
可以在 input 加上 #classTest 跟 {{ classTest.className }} 來觀察變化​
ng-untouched : 預設
ng-touched : 取得焦點 離開後
ng-pristine : 預設
ng-dirty : 內容修改過 有改過再改回來一樣的 還是dirty 
ng-valid : 驗證通過
ng-invalid : 驗證沒有通過

NgModel Properties for Validation
可以在 input 加上 #classTest="ngModel" 跟 {{ classTest.untouched}} 來觀察變化​

Styling Forms with Validation Errors
建立一個css 叫.field-error 就可以在input 加入  [class.field-error]="form.submitted && nameField.invalid"
表示當是true時 class 就會加入field-error , 當改成false 就移除field-error 也就是 當form有submit過 和 nameField驗證沒過 就加入field-error
 <div [hidden]="!form.submitted || nameField.valid" > 也是一樣 ( 錯誤訊息 )
當是ture時 div 就會hidden  , 當是false 就會顯示 也就是 還沒有submit前 或 驗證通過 一律隱藏

Submitting Forms
 <form #form="ngForm"  (ngSubmit)="onSubmit(form)">
表示當form submit時會去呼叫user-settings-form.component.ts的onSubmit方法 onSubmit(form: NgForm) {}

Handling Form Control Events
<input (blur)="onBlur(nameField)">
表示當input 觸發blur 時會去呼叫user-settings-form.component.ts的onBlur方法 onBlur(field : NgModel) {}

Creating a Data Service
用CLI 產生 service -> ng g s data

Form Posting Using Observables
用Rxjs模擬API
新增 postUserSettingsForm(userSettings: UserSettings) : Observable<UserSettings> , return of(userSettings);
this.dataService.postUserSettingsForm(this.userSettings).subscribe(
      result => console.log('success',result),
      error=>console.log('error',error)
)

HTTP Access Using HttpClient
加入 HttpClientModule
app.module.ts
import { HttpClientModule } from '@angular/common/http';
imports:  HttpClientModule
修改  postUserSettingsForm
return this.http.post('測試用URL', userSettings);

Posting a Form
https://putsreq.com/ 建立一個測試用URL
var body = JSON.parse(request.body);
body.id="168";
response.body = body;

Handling POST Errors
https://putsreq.com/ 測試用URL改成
response.status = 400;
response.body = { errorMessage:'API Fail!' };
加上檢查前端驗證成功再送出,加入postError , postErrorMessage 控制錯誤訊息
onSubmit(form: NgForm) {
    if (form.valid) { /*移除沒有改的code*/  error => this.onHttpError(error));}
    else {this.postError = true; this.postErrorMessage = "Please fix the above errors"; }
}
onHttpError(errorResponse: any) {
    this.postError = true; this.postErrorMessage = errorResponse.error.errorMessage;
}
//HTML
<div [hidden]="!postError" class="alert alert-danger">
          {{ postErrorMessage }}
</div>

Retrieving Data for Select Elements
將下拉選單 也用service設定值
service 加入
getSubscriptionTypes(): Observable<string[]> {return of(['Monthly', 'Annual', '終身']);}
ts 加入
subscriptionTypes: Observable<string[]>;
ngOnInit() { this.subscriptionTypes = this.dataService.getSubscriptionTypes(); }
Html 加入
<option *ngFor="let type of subscriptionTypes | async"> {{ type }} </option>

Form Resources at angular.io
https://angular.tw/resources
有很多整理好的UI 套件 
Angular Material

英文小教室
pristine  -> adj 原始的;清新的;純樸的

如果內容有誤請多鞭策謝謝