python创建对角矩阵
表单是许多Web应用程序的重要组成部分,是输入和编辑基于文本的数据的最常用方法。 前端JavaScript框架(例如Angular )通常具有自己的惯用方式来创建和验证表单,而您需要掌握这些表单才能提高生产力。
Angular允许您通过提供可以创建的两种类型的表单来简化此常见任务:
- 模板驱动的表单 –可以快速制作的简单表单。
- React形式 –更复杂的形式,使您可以更好地控制表单中的元素。
在本文中,我们将使用每种方法制作一个简单的示例表单,以了解其完成方式。
先决条件
您无需了解有关如何创建Angular应用程序的所有详细信息,即可了解框架在使用表单时的用处。 但是,如果您想更好地了解Angular,可以看一下有关使用Angular构建CRUD应用程序的 SitePoint系列文章。
要求
在本教程中,我们将使用Bootstrap 。 它不是Angular应用程序不可或缺的一部分,但是它将通过提供现成的样式来帮助我们进一步简化工作。
这是将其添加到应用程序中的方法:
打开命令提示符并导航到项目的文件夹
输入
npm install bootstrap@next
。 这会将最新版本的引导程序添加到项目中-
编辑
.angular-cli.json
文件,并添加指向Bootstrap CSS文件的链接"apps": [ "styles": [ "../node_modules/bootstrap/dist/css/bootstrap.css" ] ]
我们不会在此应用程序中使用Bootstrap JavaScript文件。
-
模板驱动的表单和React性表单都需要
FormsModule
。 应该将其添加到app.module
的应用程序中:import { FormsModule } from '@angular/forms'; @NgModule({ imports: [ BrowserModule, FormsModule ] })
这样一来,我们就可以继续处理表单本身了。
模板驱动的表格
让我们假设您想尽快创建一个简单的表单。 例如,您需要公司注册表。 您如何创建表格?
第一步是在视图中创建<form>
标记。
<form #companyForm="ngForm">
我们需要以两种方式修改此标记,以便提交表单并使用组件中输入字段中的信息:
- 我们将使用
ngForm
指令声明一个模板变量。 - 我们将
ngSubmit
事件绑定到将在组件中创建的方法
<form #companyForm="ngForm" (ngSubmit)="submitCompany(companyForm.form);">
稍后,我们将在组件中创建submitCompany
方法。 提交表单时将调用它,我们将通过companyForm.form
将表单中的数据传递给它。
无论表单内容如何,我们都需要一个提交按钮。 我们将使用一些Bootstrap类来设置按钮的样式。 在满足所有数据验证要求之前,最好禁用按钮。 我们可以使用为表单创建的模板变量来实现此目的。 我们将禁用属性绑定到companyForm
对象的有效属性。 这样,如果表单无效,该按钮将被禁用。
<button class="btn btn-primary" [disabled]="!companyForm.valid">Submit</button>
让我们假设我们的简单表单将包含两个字段-一个用于输入公司名称的输入字段和一个用于该公司行业的下拉字段。
创建表单输入
首先,我们为名称创建一个输入字段:
<input type="text"
class="form-control"
name="company-name">
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
现在,我们有了一个带有类型,名称和类属性的标准输入。 我们需要怎么做才能在输入中使用Angular方法?
我们需要对其应用ngModel
指令。 Angular将创建一个控件对象并将其与字段关联。 本质上,Angular在幕后为您完成了一些工作。
现在是时候提一下ngModel
要求输入字段具有名称,或者必须在ngModelOptions
表单控件定义为独立ngModelOptions
。 这不是问题,因为我们的表单已经有名称。 Angular将使用name属性来区分控件对象。
另外,在这种情况下,我们应该为输入指定一个模板变量: #nameField
。 Angular会将nameField
设置为应用于输入字段的ngModel
指令。 我们稍后将使用它进行输入字段的验证。 此变量还将允许我们在键入字段时根据字段的值执行操作。
现在,我们的输入如下所示:
<input type="text"
class="form-control"
name="company-name"
ngModel
#nameField="ngModel">
几乎相同,但有一些关键更改。
验证方式
让我们假设我们需要公司名称字段,并且其最小长度为3个字符。 这意味着我们必须在输入中添加required
和minlength
属性:
<input type="text"
class="form-control"
name="company-name"
ngModel
#nameField="ngModel"
required
minlength="3">
听起来很简单,对吧? 如果这两个要求中的任何一个都不满足,我们还将需要显示一条错误消息。 Angular允许我们在提交表单之前检查输入的值并显示相应的错误消息。
我们可以在用户输入表单时执行这种检查。 首先,最好仅在用户开始与表单进行交互之后才显示错误。 加载页面后立即显示错误消息是没有用的。 这就是为什么我们将在以下div内插入此输入的所有错误消息的原因:
<div *ngIf="nameField.touched && nameField.errors"></div>
ngIf
指令仅在特定条件为真时才允许显示div。 我们将在此处再次使用nameField
模板变量,因为它与输入关联。 在我们的例子中,只有在触摸输入并且存在问题时,div才可见。 好了,错误消息本身呢?
对于所需的每个错误消息,我们将在前面的div中放置另一个div。 我们将为错误消息创建一个新的div,然后再次使用nameField
模板变量:
<div class="alert alert-danger"
*ngIf="nameField.errors.required">
The company name is required
</div>
我们使用“ alert alert-danger”引导类来设置文本字段的样式。 nameField
变量具有errors
属性,其中包含一个对象,其中包含所有当前错误的键值对。 ngIf
指令仅在不满足“必需”条件时才显示此错误消息。 对于最小长度的错误消息,我们将使用相同的方法。
<div class="alert alert-danger"
*ngIf="nameField.errors.minlength">
The company name should be at least 3 characters long
</div>
仅当不符合minlength
要求时,该div才会可见。 在这里,我们可以使错误消息更加动态。
当前,我们在两个位置(输入的属性和文本字段)中指定了最小长度。 我们可以通过用minlength
对象的requiredLength
属性代替硬编码的“ 3”来改善这一点,如下所示:
<div class="alert alert-danger"
*ngIf="nameField.errors.minlength">
The company name should be at least {{ nameField.errors.minlength.requiredLength }} characters long
</div>
这样,错误消息中的最小长度数将取决于输入的minlength
属性。
现在,我们将对公司行业的下拉字段执行相同的操作:
<select class="form-control"
name="company-industry"
ngModel
#industryField="ngModel"
required>
我们将在与此视图关联的组件中为下拉列表创建选项列表,以避免对HTML中的值进行硬编码。
export class ContactFormComponent implements OnInit {
industries = [
{id: 1, name: "Agriculture"},
{id: 2, name: "Manufacturing"},
{id: 3, name: "Energy"},
{id: 4, name: "Transportation"},
{id: 5, name: "Finance"}
];
}
现在,我们可以通过ngFor
指令在视图中列出所有选项。 它将为组件中industries
数组中的每个元素创建一个选项标签。
<option *ngFor="let industry of industries"
[value]="industry.id">
{{ industry.name }}
</option>
该字段的验证非常容易,并且与公司名称字段的验证类似:
<div class="alert alert-danger"
*ngIf="industryField.touched && !industryField.valid">
The industry is required
</div>
现在我们的表格已准备好提交。 早些时候,我们约束ngSubmit
事件的调用方法submitCompany
; 让我们转到该组件并立即添加它:
export class ContactFormComponent implements OnInit {
submitCompany(form){
console.log(form.value);
alert("The form was submitted");
form.reset();
}
}
form
参数将包含来自表单的所有数据。 另一方面, form.value
将仅包含具有表单中字段值的对象。
在这里,我仅将结果记录在控制台中,但是您可以使用它进行任何操作。 我添加了一条警告消息,通知用户表单已提交。 这不是必需的,但是显示某种通知是一种好习惯。 form.reset()
将在提交后将表单重置为其初始状态,这意味着字段将被清空。
好吧,让我们看看表单应该是什么样的:
https://sitepoint-editors.github.io/company-registration-form/
React形式
您可以创建的另一种形式是React形式,它允许您自己为表单字段显式创建控件对象。 当您构建更复杂的表单并且希望对其行为有更多控制时,此方法是一个不错的选择。
让我们假设我们需要创建一个帐户注册表格,该表格将有两个字段,分别是电子邮件和密码。 我们还将使用Bootstrap来设置此表单的样式。
第一步是在app.module
导入ReactiveFormsModule
类,因为所有React形式都必须这样做:
import { ReactiveFormsModule } from "@angular/forms";
@NgModule({
imports: [
ReactiveFormsModule
]
})
然后,我们需要在页面的组件中导入FormGroup
和FormControl
类,以便显式定义控件对象:
import { FormGroup, FormControl } from "@angular/forms";
现在,我们应该创建FormGroup
类的实例,并在表单中指定所有字段。 简单来说,我们将列出键值对。 键将是字段的名称,值将是表单对象。
accountForm = new FormGroup({
email: new FormControl(),
password: new FormControl();
接下来,我们应该创建表单。 我们将再次需要<form>
标记。 我们将向其添加FormGroup
指令,并将HTML表单与我们在组件中创建的accountForm
表单组对象相关联:
<form [formGroup]="accountForm"></form>
接下来,我们将创建电子邮件输入字段。 我们将对其应用formControlName
指令,并将其设置为我们在组件中创建的控件列表中相应的键,即email
。
<input type="text"
class="form-control"
id="email"
formControlName="email">
我们将对密码字段执行相同的操作:
<input type="text"
id="password"
class="form-control"
formControlName="password">
验证方式
下一步是向表单添加验证。 我们不会像模板驱动表单那样使用任何HTML属性(例如“ required”)。 而是在创建表单控件对象时必须分配所有验证器。
我们将回到定义accountForm
的组件。 用于React形式的所有验证器方法都在Validators
类中定义,我们必须导入该类:
import { FormGroup, FormControl, Validators } from "@angular/forms";
然后,我们将验证器分配给控制器中的控件。 格式如下:
form = new FormGroup({
fieldname: new FormControl(
initial value,
synchronous validators,
asynchronous validators)
});
让我们假设同时需要电子邮件和密码字段。 我们还应该检查电子邮件是否有效。 此外,密码至少应包含一个大写字母,一个小写字母和一个数字。 因此,我们将对两个字段使用Validators
类中的required
和pattern
验证器。 我们将其初始值保留为空字符串。
form = new FormGroup({
email: new FormControl("",
[Validators.required,
Validators.pattern('[a-zA-z0-9_\.]+@[a-zA-Z]+\.[a-zA-Z]+')]),
password: new FormControl("",
[Validators.required,
Validators.pattern('^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{8,}$')])
});
现在,我们需要转到模板并添加验证消息。 我们将以与模板驱动表单相同的方式执行此操作。 但是,我们将以其他方式访问控制对象。 在我们的组件中,我们可以定义一个属性,该属性使我们能够以如下形式访问控件:
get email(){
return this.accountForm.get("email");
}
我们可以在模板中访问此属性。 这意味着,我们每次要指定验证消息时都不必编写this.accountForm.get("email")
,而只能使用email
。
<div *ngIf="email.touched && email.errors">
<div class="alert alert-danger" *ngIf="email.errors.required">
The email is required
</div>
</div>
<div *ngIf="email.errors">
<div class="alert alert-danger" *ngIf="email.errors.pattern">
The email is not valid
</div>
</div>
这样,在用户触摸表格并将其留空后,将显示消息“需要电子邮件”,而在用户键入时将出现消息“电子邮件无效”。 我们可以用相同的方式显示密码字段的验证消息。
让我们继续提交React式表单。 首先,我们可以通过类似于模板驱动表单的方式来禁用提交按钮:
<button class="btn btn-primary" type="submit"
[disabled]="!accountForm.valid">Sign up</button>
我们还需要将ngSubmit
事件绑定到一个函数,该函数将在提交时调用。
<form [formGroup]="accountForm" (ngSubmit)="signup()">
然后我们需要在控制器中定义该函数:
signup(){
console.log(this.accountForm.value);
alert('The form was submitted');
this.accountForm.reset();
}
现在,我们将在控制台中显示已提交的数据。 显示确认消息后,我们将清除表单字段。
异步验证
如果我们可以检查用户尝试提交的电子邮件是否已经使用,那就太好了。 即使使用异步验证器,即使用户正在输入,我们也可以执行这种检查。
在本演示中,我们将使用伪造的API- JSON Placeholder 。 这是测试应用程序的有用工具,因为它提供了各种数据。 例如,它可以为用户列表提供电子邮件,我们将其伪装为演示应用程序的现有用户列表。 您可以像使用真实API一样向其发送获取和发布请求。
我们将在应用程序中创建一个服务,该服务连接到此JSON API,并将异步验证器附加到email字段。 这样,我们将能够检查电子邮件是否已被使用。
首先,我们将创建服务。 我们可以通过Angular CLI做到这一点
ng g service server.service
然后,我们必须将服务添加到app.module
以便可以在应用程序中使用它:
import { ServerService } from "./server.service";
@NgModule({
providers: [
ServerService
],
bootstrap: [AppComponent]
})
在我们的服务中,我们需要导入Injectable
, Http
和Observable
类以及map
和filter
RxJS运算符。 然后,我们将指定测试API的URL。 得到结果后,我们将过滤它们,以查看是否有一个用户的电子邮件与该用户键入的电子邮件相匹配,我们将在执行请求时将其传递给该电子邮件。
@Injectable()
export class ServerService {
private url = "http://jsonplaceholder.typicode.com/users";
constructor(private http: Http) { }
checkUsers(email: string) {
return this.http
.get(this.url)
.map(res => res.json())
.map(users => users.filter(user => user.email === email))
.map(users => !users.length);
}
}
现在,我们必须创建验证器,它将使用此服务来检查电子邮件。 我们将创建一个新的打字稿文件custom.validators.ts 。 这将使我们能够以更有效的方式分离代码并重用验证器。 在那里,我们将导入AbstractControl
和ValidationErrors
类以及ServerService
。
import { AbstractControl, ValidationErrors } from '@angular/forms';
import { ServerService } from './server.service';
export class Customvalidators{
static checkDuplicateEmail(serverService: ServerService) {
return (control: AbstractControl) => {
return serverService.checkUsers(control.value).map(res => {
return res ? null : { duplicateEmail: true };
});
};
}
}
我们创建serverService
的实例,并调用在checkUsers
创建的checkUsers
方法。 如果一切正常,则自定义验证程序应该返回null
否则,将返回具有键值对的对象来描述错误。
现在,我们将转到组件以将异步验证器应用于电子邮件字段。 我们还必须将ServerService
导入到组件中并创建它的实例,以便执行对我们测试API的请求。
import { ServerService } from "../server.service";
constructor(private serverService: ServerService){
}
accountForm = new FormGroup({
email: new FormControl("", synchronous validators,
Customvalidators.checkDuplicateEmail(this.serverService))
});
剩下要做的唯一一件事就是添加验证消息
<div *ngIf="email.errors">
<div class="alert alert-danger" *ngIf="email.errors.duplicateEmail">
The email is already in use
</div>
</div>
现在,让我们看看表单的外观。
https://sitepoint-editors.github.io/account-registration-form/
结语
如您所见,Angular允许您对表单进行一些巧妙的技巧。 通过使它们成为模板驱动,不仅可以快速创建简单的表单,还可以根据需要在其中实现复杂的功能。
python创建对角矩阵