今天要来用 Template Driven Forms 的方式实作一个简单的登入系统,撇开 UI 不谈,具体的功能需求规格如下:
/^\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b$/gi
来检验,验证有误时需在栏位後方显示错误讯息:格式有误,请重新输入
此栏位必填
密码长度最短不得低於8码
此栏位必填
规格需求看清楚之後,我们就来开始实作吧!
实作时大家可以自己开一个专案来练习,抑或是用 Stackblitz 开一个 Angular 的专案来练习,我就不再赘述罗!
如果正在阅读此篇文章的你还不知道要怎麽开始一个 Angular 专案的话,请先阅读我的 Angular 深入浅出三十天後再来阅读此系列文章会比较恰当噢!
首先我们先准备好基本的 HTML :
<form>
<p>
<label for="account">帐号:</label>
<input type="email" name="account" id="account">
</p>
<p>
<label for="password">密码:</label>
<input type="password" name="password" id="password">
</p>
<p>
<button type="submit">登入</button>
</p>
</form>
未经美化的画面应该会长这样:
接着到 app.module.ts
里 import FormsModule
:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
imports: [
BrowserModule,
FormsModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
然後将要绑在 Template 的属性跟方法都准备好:
export class AppComponent {
// 绑定在帐号栏位上
account = '';
// 绑定在密码栏位上
password = '';
// 帐号栏位的错误讯息
accountErrorMessage = '';
// 密码栏位的错误讯息
passwordErrorMessage = '';
/**
* 绑定在帐号栏位上,当使用者改变登入帐号时,会触发此函式,并取得对应的错误讯息
*
* @param {string} account
* @param {ValidationErrors} errors
*/
accountValueChange(account: string, errors: ValidationErrors): void {
this.account = account;
this.validationCheck(errors, 'account');
}
/**
* 绑定在密码栏位上,当使用者改变密码时会触发此函式
*
* @param {string} password
* @param {ValidationErrors} errors
*/
passwordValueChange(password: string, errors: ValidationErrors): void {
this.password = password;
this.validationCheck(errors, 'password');
}
// 绑定在表单上,当使用者按下登入按钮时会触发此函式
login(): void {
// do login...
}
/**
* 透过栏位里的 ValidationErrors 来设定该栏位的错误讯息
*
* @param {ValidationErrors} errors 欲验证的栏位的错误 (by Angular)
* @param {'account' | 'password'} fieldName 栏位名称
*/
private validationCheck(
errors: ValidationErrors,
fieldName: 'account' | 'password'
): void {
let errorMessage: string;
if (!errors) {
errorMessage = '';
} else if (errors.required) {
errorMessage = '此栏位必填';
} else if (errors.pattern) {
errorMessage = '格式有误,请重新输入';
} else if (errors.minlength) {
errorMessage = '密码长度最短不得低於8码';
}
this.setErrorMessage(fieldName, errorMessage);
}
/**
* 设定指定栏位的错误讯息
*
* @param {'account' | 'password'} fieldName 欲设定错误讯息的栏位名称
* @param {string} errorMessage 欲设定的错误讯息
*/
private setErrorMessage(
fieldName: 'account' | 'password',
errorMessage: string
): void {
if (fieldName === 'account') {
this.accountErrorMessage = errorMessage;
} else {
this.passwordErrorMessage = errorMessage;
}
}
}
就可以将这些属性和方法跟 Template 绑定在一起:
<form #form="ngForm" (ngSubmit)="login()">
<p>
<label for="account">帐号:</label>
<input
type="email"
name="account"
id="account"
required
pattern="\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b"
#accountNgModel="ngModel"
[ngModel]="account"
(ngModelChange)="accountValueChange(accountNgModel.value, accountNgModel.errors)"
/>
<span class="error-message">{{ accountErrorMessage }}</span>
</p>
<p>
<label for="password">密码:</label>
<input
type="password"
name="password"
id="password"
required
#passwordNgModel="ngModel"
[minlength]="8"
[maxlength]="16"
[ngModel]="password"
(ngModelChange)="passwordValueChange(passwordNgModel.value, passwordNgModel.errors)"
/>
<span class="error-message">{{ passwordErrorMessage }}</span>
</p>
<p>
<button type="submit" [disabled]="form.invalid">登入</button>
</p>
</form>
到目前为止的程序码你看懂了多少呢?容我稍微说明一下:
首先是关於必填检核,只要 <input ...>
栏位里加上 HTML 原生的属性 ─ required
即可。
帐号栏位的格式检查则是使用原生的属性 ─ pattern
,这个属性可以直接使用正规表示法的方式来检查使用者所输入的值是否符合我们所订定的格式。不过要注意的是,头尾不需要特别加上 /^$/
,所以整串表示法只需要用到中间的部份 ─ \b[\w\.-]+@[\w\.-]+\.\w{2,4}\b
。
对这个属性较不熟悉的朋友可以参照 MDN 的说明文件。
字数长度的检核也是使用原生的属性 ─ minlength
与 maxlength
。这部份有两个地方需要特别留意:
maxlength
是会阻挡使用者输入的,当需求是要检核长度但不能阻挡使用者输入的话,就不能使用这个方式。很多人刚学会用 Angular 的朋友,在使用 ngModel
时都会忘记这两件事情:
FormsModule
input
要有 name
属性使用范本语法 #accountNgModel="ngModel"
、 #passwordNgModel="ngModel"
来取得型别为 NgModel 的物件,因为我们可以从中取得该栏位的 value
与 errors
,前者指定给其相关属性,後者用以判断该栏位的错误,以设定相对应的错误讯息。
单纯使用
#accountNgModel
与#accountNgModel="ngModel"
的差别在於前者取得的是单纯的 HTMLInputElement 物件。
#form="ngForm"
来取得型别为 NgForm 的表单物件。单纯使用
#form
与#form="ngForm"
的差别在於前者取得的是单纯的 HTMLFormElement 物件。
[disabled]="form.invalid"
的绑定,让按钮在表单无效时,无法按下登入按钮。至此,我们就完成今天的目标罗!是不是很简单呢?!
最後的结果应该要像这样:
刚开始学习 Angular 的朋友,通常都会因为不熟悉 Angular 的语法而导致明明很简单的功能却要弄得很复杂。
今天的学习重点主要有以下三点:
#accountNgModel="ngModel"
与 #form="ngForm"
。ValidationErrors
取得相应的错误讯息。我会将今日的实作程序码放在 Stackblitz 上供大家参考,建议大家在看我的实作之前,先按照需求规格自己做一遍,之後再跟我的对照,看看自己的实作跟我的实作不同的地方在哪里、有什麽好处与坏处,如此反覆咀嚼消化後,我相信你一定可以进步地非常快!
如果有任何的问题或是回馈,也都非常欢迎留言给我让我知道噢!
2021-09-19 22:54:50
,感谢热心读者「程凯大」指正错误,已移除所有的 FormControl
,原因是因为在 Template Driven Forms 的范围里, NgModel 本身已有我们所需之属性,是我自己猪头舍近求远,再次衷心感谢。
>>: 【Day17】 data-test这个属性是用来干嘛的...? 这东西能吃吗 (╯✧∇✧)╯ !?
练习范例教学 六指渊:https://www.sixvfx.com/rolling_paper 开始...
MongoDB 是一个 NoSQL 实现。NoSQL 在具有高吞吐量的应用程序中可以非常高性能。 没...
本篇重点 透过Pandas读取资料及做OHLC转换 DataFrame.resample中的Left...
这篇会来教大家如何透过 Firebase 在你的 iOS App 上实作注册以及登入功能 透过 Fi...
在开发的过程一定会面临各式的测试,以及功能的增减。对於文件的编写也会有相同的要求。一般来说,个人开发...