65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Angular 5 中的模板驱动表单进行验证

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (2投票s)

2018 年 4 月 22 日

CPOL

5分钟阅读

viewsIcon

13551

如何使用 Angular 5 中的模板驱动表单进行验证

引言

在这篇文章中,我们将了解如何在 Angular 5 中使用模板驱动表单进行验证。这只是一种你可以遵循的不同方法,因为我们在上一篇文章中已经讨论了另一种方法。在本文结束时,你将了解如何使用模板驱动表单在 Angular 5 应用程序中实现验证。这篇文章是“开发 Angular 5 应用”系列课程的延续。如果你还没有阅读过前面的文章,我强烈建议你这样做。你可以在下面找到指向先前帖子的链接。希望你喜欢这篇文章。

开发 Angular 5 应用系列

这些是本系列的上一篇文章。请继续阅读。

  1. 什么是新的,以及如何设置我们的第一个 Angular 5 应用程序
  2. Angular 5 基本演示项目概述
  3. 在 Angular 5 应用中生成你的第一个组件和模块
  4. 在 Angular 5 应用中实现验证

背景

无论用什么语言开发,验证在所有应用程序中都起着至关重要的作用。而且由于它是一个重要的部分,因此有许多方法可以实现它。在这里,我们将看到模板驱动表单的方法。

Using the Code

建议从 GitHub 克隆项目,以便你可以自己尝试所有内容。现在,让我们继续编写一些代码。

安装 Bootstrap

在开始之前,让我们在应用程序中安装 Bootstrap。

PS F:\My Projects\ng5> npm install bootstrap --save

由于我们正在使用 Angular CLI 开发此应用程序,因此可以在 Angular-CLI.json 文件中添加 Bootstrap 的引用。添加引用后,该文件的 styles 部分将如下所示。

"styles": [
        "styles.css",
        "../node_modules/bootstrap/dist/css/bootstrap.min.css"
      ]

请注意,在我们的应用程序中配置 Bootstrap 还有许多其他方法,此处我们不对此进行解释。

将 ngForm 导入到变量中

让我们清理我们 Registration 组件中的代码,并添加一个新的 form,其中有一个 form 变量,此 form 变量可以保存我们 form 的值。你可以使用此变量做很多事情,目前,我们可以将其视为我们的模型值容器。

<div class="container">
  <div class="row">
    <div class="no-float center-block col-lg-4 col-sm-4">
      <mat-card>
        <mat-card-header>
          <img mat-card-avatar 
           src="../../../assets/images/App-login-manager-icon.png">
          <mat-card-title>Sign up</mat-card-title>
          <mat-card-subtitle>Trust us for your data, 
                             and sign up</mat-card-subtitle>
        </mat-card-header>
        <mat-card-content>
          <form #regsiterForm="ngForm" (ngSubmit)="register(regsiterForm)">
          </form>
        </mat-card-content>
      </mat-card>
    </div>
  </div>
</div>
import { OnInit, Component } from "@angular/core";

@Component({
  selector: 'app-registration',
  templateUrl: './registration.component.html',
  styleUrls: ['./registration.component.css']
})
export class RegistrationComponent implements OnInit {
  constructor() {
  }

  ngOnInit() {
  }
}

使用模板驱动表单为用户名字段实现验证

既然我们已经创建了表单,现在是时候将我们的输入控件生成到其中了。

<form #regsiterForm="ngForm" (ngSubmit)="register(regsiterForm)">
    <div class="signup-fields">
        <div class="form-group">
            <input type="text" required name="userName" 
             class="form-control" placeholder="User Name">
        </div>
        <div>
            <button class="btn btn-primary btn-block" type="submit">Signup</button>
        </div>
    </div>
</form>

上面我们有一个简单的 HTML 模板驱动表单,我们将在其中引入验证。现在让我们修改 userName 字段。

<input type="text" [(ngModel)]="userName" #userName="ngModel" 
required name="userName" class="form-control" placeholder="User Name">

通过上面的代码,我们试图创建一个引用变量 userName 并将输入值赋给它。基本上,这是双向绑定,我们可以从组件设置数据并在表单中更新它,反之亦然。现在,如果你运行应用程序,你应该会看到如下错误:

Uncaught Error: Cannot assign to a reference or variable!
    at _AstToIrVisitor.visitPropertyWrite (compiler.js:26025)
    at PropertyWrite.visit (compiler.js:4585)
    at convertActionBinding (compiler.js:25475)
    at eval (compiler.js:27987)
    at Array.forEach (<anonymous>)
    at ViewBuilder._createElementHandleEventFn (compiler.js:27983)
    at nodes.(anonymous function) 
    (webpack-internal:///./node_modules/@angular/compiler/esm5/compiler.js:27620:27)
    at eval (compiler.js:27928)
    at Array.map (<anonymous>)
    at ViewBuilder._createNodeExpressions (compiler.js:27927)

这是因为我们将模型和引用变量使用了相同的名称。所以我们应该改变它。为此,让我们创建一个 User Model (user.model.ts) 并将其引用到我们的 Register 组件。

export class User {
    id: any;
    userName: string;
    email: string;
    userRole: string;
    profileImage: string;
    phoneNumber: string;
    firstName: string;
    lastName: string;
}
import { User } from '../models/user.model'

现在我们可以将输入修改如下:

<input type="text" [(ngModel)]="user.userName" #userName="ngModel" 
required name="userName" class="form-control" placeholder="User Name">

请务必在 registration 组件中声明一个 user。

export class RegistrationComponent implements OnInit {
  user = new User();
  constructor() {
  }

  ngOnInit() {
  }
}

现在,如果你运行应用程序,你会发现 Submit 按钮仅在表单有效时才会启用,也就是说,只有当你输入用户名字段中的任何值时。

修饰验证消息

现在我们知道我们的表单工作正常,但如果我们没有在字段中提供任何值,我们难道不需要给用户一条消息吗?让我们在 HTML 中添加更多标记。

<div class="form-group" [class.has-error]="userName.invalid" 
                        [class.has-success]="userName.valid">
    <input type="text" [(ngModel)]="user.userName" 
         #userName="ngModel" required name="userName" 
                    class="form-control" placeholder="User Name">
    <span class="help-block" *ngIf="userName.errors?.required">
                  User Name is required
                </span>
</div>

通过检查 userName 字段的 valid 和 invalid 属性,我们动态地启用了 "has-error" 和 "has-success" 类。如果我们的 userName 模型中存在任何必需字段错误,我们还会显示一个新的 span 标签中的必填字段消息。现在,如果你运行你的应用程序,你会看到验证工作正常。

但是,这种验证不是默认显示的吗?我们应该只在用户触摸过我们的字段但又拒绝输入任何内容时才显示消息,对吧?让我们在标记中添加 "userName.touched"。

<div class="form-group" [class.has-error]="userName.invalid && 
                  userName.touched" [class.has-success]="userName.valid">
    <input type="text" [(ngModel)]="user.userName" #userName="ngModel" 
             required name="userName" class="form-control" placeholder="User Name">
    <span class="help-block" *ngIf="userName.errors?.required && userName.touched">
                  User Name is required
                </span>
</div>

也为其他字段实现验证

现在是时候在其他字段中实现相同的功能了。

<div class="container" style="margin-top:100px;">
  <div class="row justify-content-center align-items-center">
    <div class="col-lg-4 col-sm-4 center-block ">
      <mat-card>
        <mat-card-header>
          <img mat-card-avatar src="../../../assets/images/App-login-manager-icon.png">
          <mat-card-title>Sign up</mat-card-title>
          <mat-card-subtitle>Trust us for your data, and sign up</mat-card-subtitle>
        </mat-card-header>
        <mat-card-content>
          <form #regsiterForm="ngForm" (ngSubmit)="register(user)">
            <div class="signup-fields">
              <div class="form-group" [class.has-error]="userName.invalid && 
                                       userName.touched" 
                                      [class.has-success]="userName.valid">
                <input type="text" [(ngModel)]="user.userName" 
                         #userName="ngModel" required name="userName" 
                         class="form-control" placeholder="User Name">
                <span class="help-block" *ngIf="userName.errors?.required && 
                                         userName.touched">
                  User Name is required
                </span>
              </div>
              <div class="form-group" [class.has-error]="email.invalid && 
                                 email.touched" [class.has-success]="email.valid">
                <input type="text" required [email]="user.email 
                 !== ''" [(ngModel)]="user.email" name="email" 
                 class="form-control" placeholder="Email"
                  #email="ngModel">
                <span class="help-block" 
                      *ngIf="email.errors?.required && email.touched">
                  Email is required
                </span>
                <span class="help-block" 
                      *ngIf="email.errors?.email && email.touched">
                  Email is invalid
                </span>
              </div>
              <div class="form-group" [class.has-error]="password.invalid && 
                   password.touched" [class.has-success]="password.valid">
                <input type="password" [(ngModel)]="user.password" 
                   required class="form-control" name="password" 
                   placeholder="Password" #password="ngModel">
                <span class="help-block" *ngIf="password.invalid && password.touched">
                  Password is required
                </span>
              </div>
              <div class="form-group" 
               [class.has-error]="confirmPasswordControl.invalid && 
                       confirmPasswordControl.touched" 
                       [class.has-success]="confirmPasswordControl.valid">
                <input type="password" required class="form-control" 
                       name="confirmPassword" placeholder="Confirm Password" 
                       [(ngModel)]="confirmPassword"
                  #confirmPasswordControl="ngModel">
                <span class="help-block" 
                 *ngIf="confirmPasswordControl.errors?.required && 
                      confirmPasswordControl.touched">
                  Confirm password is required
                </span>
              </div>
              <div>
                <button class="btn btn-primary btn-block" type="submit" 
                          [disabled]="regsiterForm.invalid">Signup</button>
              </div>
            </div>
          </form>
        </mat-card-content>
      </mat-card>
    </div>
  </div>
</div>

对于电子邮件验证,我们添加了一个额外的属性并将条件设置为 [email]="user.email !== ''",这是为了避免必需验证和电子邮件验证同时显示。如果用户触摸了该字段但没有输入任何值,这将显示必需消息,并且只有在输入的值不是有效电子邮件时,电子邮件验证才会生效。听起来不错吧?

添加 Register 函数

最后,让我们添加我们的 register 函数。

import { OnInit, Component } from "@angular/core";
import { User } from '../models/user.model';
@Component({
  selector: 'app-registration',
  templateUrl: './registration.component.html',
  styleUrls: ['./registration.component.css']
})
export class RegistrationComponent implements OnInit {
  user = new User();
  constructor() {
  }

  ngOnInit() {
  }

  register(user: User): void{
    console.log(user);
  }
}

完成后,让我们打开浏览器控制台并查看数据。

在这里,我们已经看到了如何使用模板驱动表单实现验证。我将在下一篇文章中介绍如何使用指令实现自定义验证器,用于比较我们的密码和确认密码字段。在那之前,再见。

结论

非常感谢你的阅读。我是否遗漏了你认为需要的东西?你觉得这篇文章有用吗?我希望你喜欢这篇文章。请分享你宝贵的建议和反馈。

现在轮到你了。你有什么想法?

没有评论的博客不是博客,但请尽量保持主题。如果你有一个与此帖子无关的问题,最好将其发布在 C# Corner、Code Project、Stack Overflow、ASP.NET Forum 上,而不是在此评论。在 Twitter 或电子邮件中向我发送你问题的链接,如果我能提供帮助,我一定会尝试。

历史

  • 2018年4月22日:初始版本
© . All rights reserved.