Angular For Beginners - 16. Template Driven Forms (ngForm)
Angular 以其表单模块而闻名。
Angular 有两种类型的表单: Template 以及 Reactive:
Template 表单的特点:简单,神奇,一键点击。
Reactive 表单的特点:可扩展,复杂,可测试。
多数情况下都可以使用 Template 表单,但如果需要应对用户输入伪造的数据等情况,就需要使用更为复杂的 Reactive 表单。
ngModel
在 app 中频繁出现,它不仅仅局限于表单,还可用于数据绑定。
ngForm
特定于 template 表单,用于表单初始化。
1. Template Driven Form 使用步骤
-
Build(构建):设置 html,model 等
-
Bind (绑定) : 如下的代码使用了双向绑定
html
<form #form="ngForm">
<input [(ngModel)]="modelName.property" name="property" />
</form>
- Track(追踪):执行简单的 validation
- Submit(提交)
2. 生成表单组件
app 右键 -> Generate Component,名称设为 pokemon-template-form
3. pokemon.service.ts
增加一个新的函数
ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Pokemon } from '../models/pokemon';
import { Observable } from 'rxjs';
const POKEMON_API = 'http://localhost:3000/pokemon';
@Injectable({
providedIn: 'root',
})
export class PokemonService {
constructor(private http: HttpClient) {
console.log(this.http);
}
// new function
getPokemon(id: number) {
return this.http.get<Pokemon>(`${POKEMON_API}/1`);
}
getPokemons(): Observable<Pokemon[]> {
return this.http.get<Pokemon[]>(POKEMON_API);
}
}
4. pokemon-template-form.component.ts
:
ts
import { Component, OnInit } from '@angular/core';
import { Pokemon } from '../models/pokemon';
import { PokemonService } from '../services/pokemon.service';
@Component({
selector: 'app-pokemon-template-form',
templateUrl: './pokemon-template-form.component.html',
styleUrls: ['./pokemon-template-form.component.css'],
})
export class PokemonTemplateFormComponent implements OnInit {
pokemon!: Pokemon;
// 引入服务
constructor(private pokemonService: PokemonService) {}
ngOnInit() {
// 这部分代码放在 ngOnInit 是更好的做法,非必须。
this.pokemonService.getPokemon(1).subscribe((data: Pokemon) => {
this.pokemon = data;
});
}
}
5. 设置 HTML
其中 |
是 pipe,是一个小的 add-on, 可以加到 HTML 中,pokemon | json
意思是说,将 pokemon
以 json 格式显示。
pokemon-template-form.component.html
:
html
<form>
Form!
</form>
MODEL: {{ pokemon | json}}
app.component.html
:
html
<app-pokemon-template-form></app-pokemon-template-form>
6. 运行 ng serve
一切正常运行:
7. 连接模板表单
html
<form #form="ngForm">
Form!
</form>
MODEL: {{ pokemon | json}}
如果 ngForm
出现如下错误提示:
No directive found with exportAs 'ngForm'.ngtsc(-998003)
pokemon-template-form.component.ts(5, 27): Error occurs in the template of component PokemonTemplateFormComponent.
那么在 app.module.ts
中 import FormsModule:
ts
@NgModule({
declarations: [AppComponent, PokemonTemplateFormComponent],
// add FormsModule
imports: [BrowserModule, AppRoutingModule, PokemonBaseModule, FormsModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
修改 pokemon-template-form.component.html
:
html
<form #form="ngForm">
Pokemon Name:
<input type="text" [(ngModel)]="pokemon.name" name="name" />
</form>
<div>MODEL: {{ pokemon | json }}</div>
<div>FORM: {{ form.value | json }}</div>
因为 console 会出现错误 "ERROR TypeError: Cannot read properties of undefined (reading 'name')",所以我将整段代码放在了 <div *ngIf="pokemon"> <div>
中。
html
<div *ngIf="pokemon">
<form #form="ngForm">
Pokemon Name:
<input type="text" [(ngModel)]="pokemon.name" name="name" />
</form>
<div>MODEL: {{ pokemon | json }}</div>
<div>FORM: {{ form.value | json }}</div>
</div>
运行结果: