[Angular] 笔记 12:模板驱动表单 - ngForm

Angular For Beginners - 16. Template Driven Forms (ngForm)

Angular 以其表单模块而闻名。

Angular 有两种类型的表单: Template 以及 Reactive:

Template 表单的特点:简单,神奇,一键点击。

Reactive 表单的特点:可扩展,复杂,可测试。

多数情况下都可以使用 Template 表单,但如果需要应对用户输入伪造的数据等情况,就需要使用更为复杂的 Reactive 表单。


ngModel 在 app 中频繁出现,它不仅仅局限于表单,还可用于数据绑定。
ngForm 特定于 template 表单,用于表单初始化。

1. Template Driven Form 使用步骤

  1. Build(构建):设置 html,model 等

  2. Bind (绑定) : 如下的代码使用了双向绑定

html 复制代码
<form #form="ngForm">
  <input [(ngModel)]="modelName.property" name="property" />
</form>
  1. Track(追踪):执行简单的 validation
  2. 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>

运行结果:

相关推荐
To_OC2 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
vipbic3 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy3 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志3 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble4 小时前
c端系统,其实更像一个信息展示平台
前端
李姆斯5 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
疯狂打码的少年5 小时前
【软件工程】软件开发模型:增量模型与迭代模型
笔记·软件工程
Generalzy6 小时前
从本地 Demo 到生产级检索:Milvus 学习笔记(3)
笔记·学习·milvus
名字还没想好☜6 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司6 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能