- Form表单
- 表单
- 表单项 nz-form-item
- 表单标签 nz-form-label
- 表单域 nz-form-control
- 代码演示
- API
- 单独引入此组件
- nz-formcomponent
- nz-form-itemcomponent
- nz-form-labelcomponent
- nz-form-controlcomponent
- nz-form-explaincomponent
- nz-form-extracomponent
- nz-form-splitcomponent
- nz-form-textcomponent
- 表单
Form表单
具有数据收集、校验和提交功能的表单,包含复选框、单选框、输入框、下拉选择框等元素。
该组件需要与 Angular表单 结合使用,开发者根据需要可以自由选择 响应式表单 或 模板驱动表单.
使用该组件前请确保您已经阅读并掌握了 Forms 的使用方式。
表单
我们提供了以下三种排列方式:
- 水平排列:标签和表单控件水平排列;(默认)
- 垂直排列:标签和表单控件上下垂直排列;
- 行内排列:表单项水平行内排列。
表单项 nz-form-item
表单项用于区分表单中不同的区域,包含表单域和表单标签(可选)。
表单标签 nz-form-label
用于标示当前表单项的内容,可选。
表单域 nz-form-control
表单一定会包含表单域,表单域可以是输入控件,标准表单域,标签,下拉菜单,文本域等。
<form nz-form>
<nz-form-item>
<nz-form-label [nzSpan]="6" nzFor="email">E-mail</nz-form-label>
<nz-form-control [nzSpan]="14">
<input nz-input name="email" type="email" id="email">
</nz-form-control>
</nz-form-item >
</form>
代码演示
水平登录栏
水平登录栏,常用在顶部导航栏中。
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'nz-demo-form-horizontal-login',
template: `
<form nz-form [nzLayout]="'inline'" [formGroup]="validateForm" (ngSubmit)="submitForm()">
<nz-form-item>
<nz-form-control>
<nz-input-group [nzPrefix]="prefixUser">
<input formControlName="userName" nz-input placeholder="Username" />
</nz-input-group>
<nz-form-explain *ngIf="validateForm.get('userName')?.dirty && validateForm.get('userName')?.errors"
>Please input your username!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control>
<nz-input-group [nzPrefix]="prefixLock">
<input formControlName="password" nz-input type="password" placeholder="Password" />
</nz-input-group>
<nz-form-explain *ngIf="validateForm.get('password')?.dirty && validateForm.get('password')?.errors"
>Please input your Password!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control>
<button nz-button nzType="primary" [disabled]="!validateForm.valid">Log in</button>
</nz-form-control>
</nz-form-item>
</form>
<ng-template #prefixUser><i nz-icon type="user"></i></ng-template>
<ng-template #prefixLock><i nz-icon type="lock"></i></ng-template>
`
})
export class NzDemoFormHorizontalLoginComponent implements OnInit {
validateForm: FormGroup;
submitForm(): void {
for (const i in this.validateForm.controls) {
this.validateForm.controls[i].markAsDirty();
this.validateForm.controls[i].updateValueAndValidity();
}
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.validateForm = this.fb.group({
userName: [null, [Validators.required]],
password: [null, [Validators.required]],
remember: [true]
});
}
}
登录框
普通的登录框,可以容纳更多的元素。
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'nz-demo-form-normal-login',
template: `
<form nz-form [formGroup]="validateForm" class="login-form" (ngSubmit)="submitForm()">
<nz-form-item>
<nz-form-control>
<nz-input-group [nzPrefix]="prefixUser">
<input type="text" nz-input formControlName="userName" placeholder="Username" />
</nz-input-group>
<nz-form-explain *ngIf="validateForm.get('userName')?.dirty && validateForm.get('userName')?.errors"
>Please input your username!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control>
<nz-input-group [nzPrefix]="prefixLock">
<input type="password" nz-input formControlName="password" placeholder="Password" />
</nz-input-group>
<nz-form-explain *ngIf="validateForm.get('password')?.dirty && validateForm.get('password')?.errors"
>Please input your Password!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control>
<label nz-checkbox formControlName="remember">
<span>Remember me</span>
</label>
<a class="login-form-forgot" class="login-form-forgot">Forgot password</a>
<button nz-button class="login-form-button" [nzType]="'primary'">Log in</button>
Or
<a href="">register now!</a>
</nz-form-control>
</nz-form-item>
</form>
<ng-template #prefixUser><i nz-icon type="user"></i></ng-template>
<ng-template #prefixLock><i nz-icon type="lock"></i></ng-template>
`,
styles: [
`
.login-form {
max-width: 300px;
}
.login-form-forgot {
float: right;
}
.login-form-button {
width: 100%;
}
`
]
})
export class NzDemoFormNormalLoginComponent implements OnInit {
validateForm: FormGroup;
submitForm(): void {
for (const i in this.validateForm.controls) {
this.validateForm.controls[i].markAsDirty();
this.validateForm.controls[i].updateValueAndValidity();
}
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.validateForm = this.fb.group({
userName: [null, [Validators.required]],
password: [null, [Validators.required]],
remember: [true]
});
}
}
注册新用户
用户填写必须的信息以注册新用户。
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'nz-demo-form-register',
template: `
<form nz-form [formGroup]="validateForm" (ngSubmit)="submitForm()">
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="email">E-mail</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24">
<input nz-input formControlName="email" id="email" />
<nz-form-explain *ngIf="validateForm.get('email')?.dirty && validateForm.get('email')?.errors">
The input is not valid E-mail!
</nz-form-explain>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="password" nzRequired>Password</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24">
<input
nz-input
type="password"
id="password"
formControlName="password"
(ngModelChange)="updateConfirmValidator()"
/>
<nz-form-explain *ngIf="validateForm.get('password')?.dirty && validateForm.get('password')?.errors"
>Please input your password!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="checkPassword" nzRequired>Confirm Password</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24">
<input nz-input type="password" formControlName="checkPassword" id="checkPassword" />
<nz-form-explain
*ngIf="validateForm.get('checkPassword')?.dirty && validateForm.get('checkPassword')?.errors"
>
<ng-container *ngIf="validateForm.get('checkPassword')?.hasError('required')">
Please confirm your password!
</ng-container>
<ng-container *ngIf="validateForm.get('checkPassword')?.hasError('confirm')">
Two passwords that you enter is inconsistent!
</ng-container>
</nz-form-explain>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="nickname" nzRequired>
<span>
Nickname
<i
nz-icon
nz-tooltip
nzTitle="What do you want other to call you"
type="question-circle"
theme="outline"
></i>
</span>
</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24">
<input nz-input id="nickname" formControlName="nickname" />
<nz-form-explain *ngIf="validateForm.get('nickname')?.dirty && validateForm.get('nickname')?.errors"
>Please input your nickname!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="phoneNumber" nzRequired>Phone Number</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24" [nzValidateStatus]="validateForm.controls['phoneNumber']">
<nz-input-group [nzAddOnBefore]="addOnBeforeTemplate">
<ng-template #addOnBeforeTemplate>
<nz-select formControlName="phoneNumberPrefix" style="width: 70px;">
<nz-option nzLabel="+86" nzValue="+86"></nz-option>
<nz-option nzLabel="+87" nzValue="+87"></nz-option>
</nz-select>
</ng-template>
<input formControlName="phoneNumber" id="'phoneNumber'" nz-input />
</nz-input-group>
<nz-form-explain *ngIf="validateForm.get('phoneNumber')?.dirty && validateForm.get('phoneNumber')?.errors"
>Please input your phone number!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="website" nzRequired>Website</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24">
<input nz-input id="website" formControlName="website" placeholder="website" />
<nz-form-explain *ngIf="validateForm.get('website')?.dirty && validateForm.get('website')?.errors"
>Please input website!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="captcha" nzRequired>Captcha</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24">
<div nz-row [nzGutter]="8">
<div nz-col [nzSpan]="12">
<input nz-input formControlName="captcha" id="captcha" />
</div>
<div nz-col [nzSpan]="12">
<button nz-button (click)="getCaptcha($event)">Get captcha</button>
</div>
</div>
<nz-form-explain *ngIf="validateForm.get('captcha')?.dirty && validateForm.get('captcha')?.errors"
>Please input the captcha you got!</nz-form-explain
>
<nz-form-extra>We must make sure that your are a human.</nz-form-extra>
</nz-form-control>
</nz-form-item>
<nz-form-item nz-row style="margin-bottom:8px;">
<nz-form-control [nzSpan]="14" [nzOffset]="6">
<label nz-checkbox formControlName="agree">
<span>I have read the <a>agreement</a></span>
</label>
</nz-form-control>
</nz-form-item>
<nz-form-item nz-row style="margin-bottom:8px;">
<nz-form-control [nzSpan]="14" [nzOffset]="6">
<button nz-button nzType="primary">Register</button>
</nz-form-control>
</nz-form-item>
</form>
`,
styles: [
`
[nz-form] {
max-width: 600px;
}
`
]
})
export class NzDemoFormRegisterComponent implements OnInit {
validateForm: FormGroup;
submitForm(): void {
for (const i in this.validateForm.controls) {
this.validateForm.controls[i].markAsDirty();
this.validateForm.controls[i].updateValueAndValidity();
}
}
updateConfirmValidator(): void {
/** wait for refresh value */
Promise.resolve().then(() => this.validateForm.controls.checkPassword.updateValueAndValidity());
}
confirmationValidator = (control: FormControl): { [s: string]: boolean } => {
if (!control.value) {
return { required: true };
} else if (control.value !== this.validateForm.controls.password.value) {
return { confirm: true, error: true };
}
return {};
};
getCaptcha(e: MouseEvent): void {
e.preventDefault();
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.validateForm = this.fb.group({
email: [null, [Validators.email, Validators.required]],
password: [null, [Validators.required]],
checkPassword: [null, [Validators.required, this.confirmationValidator]],
nickname: [null, [Validators.required]],
phoneNumberPrefix: ['+86'],
phoneNumber: [null, [Validators.required]],
website: [null, [Validators.required]],
captcha: [null, [Validators.required]],
agree: [false]
});
}
}
高级搜索
三列栅格式的表单排列方式,常用于数据表格的高级搜索。
有部分定制的样式代码,由于输入标签长度不确定,需要根据具体情况自行调整。
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'nz-demo-form-advanced-search',
template: `
<form nz-form [formGroup]="validateForm" class="ant-advanced-search-form">
<div nz-row [nzGutter]="24">
<div nz-col [nzSpan]="8" *ngFor="let control of controlArray" [style.display]="control.show ? 'block' : 'none'">
<nz-form-item nzFlex>
<nz-form-label [nzFor]="'field' + control.index">Field {{ control.index }}</nz-form-label>
<nz-form-control>
<input
nz-input
placeholder="placeholder"
[formControlName]="'field' + control.index"
[attr.id]="'field' + control.index"
/>
</nz-form-control>
</nz-form-item>
</div>
</div>
<div nz-row>
<div nz-col [nzSpan]="24" style="text-align: right;">
<button nz-button [nzType]="'primary'">Search</button>
<button nz-button (click)="resetForm()">Clear</button>
<a style="margin-left:8px;font-size:12px;" (click)="toggleCollapse()">
Collapse
<i nz-icon [type]="isCollapse ? 'down' : 'up'"></i>
</a>
</div>
</div>
</form>
<div class="search-result-list">
Search Result List
</div>
`,
styles: [
`
.ant-advanced-search-form {
padding: 24px;
background: #fbfbfb;
border: 1px solid #d9d9d9;
border-radius: 6px;
}
.search-result-list {
margin-top: 16px;
border: 1px dashed #e9e9e9;
border-radius: 6px;
background-color: #fafafa;
min-height: 200px;
text-align: center;
padding-top: 80px;
}
[nz-form-label] {
overflow: visible;
}
button {
margin-left: 8px;
}
`
]
})
export class NzDemoFormAdvancedSearchComponent implements OnInit {
validateForm: FormGroup;
controlArray: any[] = [];
isCollapse = true;
toggleCollapse(): void {
this.isCollapse = !this.isCollapse;
this.controlArray.forEach((c, index) => {
c.show = this.isCollapse ? index < 6 : true;
});
}
resetForm(): void {
this.validateForm.reset();
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.validateForm = this.fb.group({});
for (let i = 0; i < 10; i++) {
this.controlArray.push({ index: i, show: i < 6 });
this.validateForm.addControl(`field${i}`, new FormControl());
}
}
}
动态增减表单项
动态增加、减少表单项。
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'nz-demo-form-dynamic-form-item',
template: `
<form nz-form [formGroup]="validateForm" (ngSubmit)="submitForm()">
<nz-form-item *ngFor="let control of controlArray; let i = index">
<nz-form-label [nzXs]="24" [nzSm]="4" *ngIf="i == 0" [nzFor]="control.controlInstance"
>Passengers</nz-form-label
>
<nz-form-control [nzXs]="24" [nzSm]="20" [nzOffset]="i == 0 ? 0 : 4">
<input
nz-input
style="width: 60%; margin-right:8px;"
placeholder="placeholder"
[attr.id]="control.id"
[formControlName]="control.controlInstance"
/>
<i nz-icon type="minus-circle-o" class="dynamic-delete-button" (click)="removeField(control, $event)"></i>
<nz-form-explain
*ngIf="
getFormControl(control.controlInstance)?.dirty &&
getFormControl(control.controlInstance)?.hasError('required')
"
>
Please input passenger's name or delete this field.
</nz-form-explain>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzXs]="{ span: 24, offset: 0 }" [nzSm]="{ span: 20, offset: 4 }">
<button nz-button nzType="dashed" style="width:60%" (click)="addField($event)">
<i nz-icon type="plus"></i> Add field
</button>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzXs]="{ span: 24, offset: 0 }" [nzSm]="{ span: 20, offset: 4 }">
<button nz-button nzType="primary">Submit</button>
</nz-form-control>
</nz-form-item>
</form>
`,
styles: [
`
.dynamic-delete-button {
cursor: pointer;
position: relative;
top: 4px;
font-size: 24px;
color: #999;
transition: all 0.3s;
}
.dynamic-delete-button:hover {
color: #777;
}
[nz-form] {
max-width: 600px;
}
`
]
})
export class NzDemoFormDynamicFormItemComponent implements OnInit {
validateForm: FormGroup;
controlArray: Array<{ id: number; controlInstance: string }> = [];
addField(e?: MouseEvent): void {
if (e) {
e.preventDefault();
}
const id = this.controlArray.length > 0 ? this.controlArray[this.controlArray.length - 1].id + 1 : 0;
const control = {
id,
controlInstance: `passenger${id}`
};
const index = this.controlArray.push(control);
console.log(this.controlArray[this.controlArray.length - 1]);
this.validateForm.addControl(
this.controlArray[index - 1].controlInstance,
new FormControl(null, Validators.required)
);
}
removeField(i: { id: number; controlInstance: string }, e: MouseEvent): void {
e.preventDefault();
if (this.controlArray.length > 1) {
const index = this.controlArray.indexOf(i);
this.controlArray.splice(index, 1);
console.log(this.controlArray);
this.validateForm.removeControl(i.controlInstance);
}
}
getFormControl(name: string): AbstractControl {
return this.validateForm.controls[name];
}
submitForm(): void {
for (const i in this.validateForm.controls) {
this.validateForm.controls[i].markAsDirty();
this.validateForm.controls[i].updateValueAndValidity();
}
console.log(this.validateForm.value);
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.validateForm = this.fb.group({});
this.addField();
}
}
时间类控件
时间类组件的输入和输出类型均为 Date
类型,可以通过 date-fns 工具库进行进一步的处理。
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'nz-demo-form-time-related-controls',
template: `
<form nz-form [formGroup]="validateForm" (ngSubmit)="submitForm()">
<nz-form-item>
<nz-form-label [nzSm]="8" [nzXs]="24" nzRequired>DatePicker</nz-form-label>
<nz-form-control [nzSm]="16" [nzXs]="24">
<nz-date-picker formControlName="datePicker"></nz-date-picker>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="8" [nzXs]="24" nzRequired>DatePicker[ShowTime]</nz-form-label>
<nz-form-control [nzSm]="16" [nzXs]="24">
<nz-date-picker nzShowTime formControlName="datePickerTime"></nz-date-picker>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="8" [nzXs]="24" nzRequired>MonthPicker</nz-form-label>
<nz-form-control [nzSm]="16" [nzXs]="24">
<nz-month-picker formControlName="monthPicker"></nz-month-picker>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="8" [nzXs]="24" nzRequired>RangePicker</nz-form-label>
<nz-form-control [nzSm]="16" [nzXs]="24">
<nz-range-picker formControlName="rangePicker"></nz-range-picker>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="8" [nzXs]="24" nzRequired>RangePicker[showTime]</nz-form-label>
<nz-form-control [nzSm]="16" [nzXs]="24">
<nz-range-picker nzShowTime formControlName="rangePickerTime"></nz-range-picker>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSm]="8" [nzXs]="24" nzRequired>TimePicker</nz-form-label>
<nz-form-control [nzSm]="16" [nzXs]="24">
<nz-time-picker formControlName="timePicker"></nz-time-picker>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzXs]="{ span: 24, offset: 0 }" [nzSm]="{ span: 16, offset: 8 }">
<button nz-button nzType="primary">Submit</button>
</nz-form-control>
</nz-form-item>
</form>
`,
styles: [
`
form {
max-width: 600px;
}
`
]
})
export class NzDemoFormTimeRelatedControlsComponent implements OnInit {
validateForm: FormGroup;
submitForm(): void {
console.log(this.validateForm.value);
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.validateForm = this.fb.group({
datePicker: [null],
datePickerTime: [null],
monthPicker: [null],
rangePicker: [[]],
rangePickerTime: [[]],
timePicker: [null]
});
}
}
响应式表单验证
我们在 nz-form-control
上 提供了 nzValidateStatus
nzHasFeedback
等属性,当使用响应式表单时,可以自己定义校验的时机和内容。
nzValidateStatus
: 校验状态,默认自动从nz-form-control
中的NgControl
获得校验状态,也可以手动指定为特定的NgControl
。nzHasFeedback
:用于给输入框添加反馈图标。nz-form-explain
:设置校验文案。
import { Component } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, ValidationErrors, Validators } from '@angular/forms';
import { Observable, Observer } from 'rxjs';
@Component({
selector: 'nz-demo-form-validate-reactive',
template: `
<form nz-form [formGroup]="validateForm" (ngSubmit)="submitForm($event, validateForm.value)">
<nz-form-item>
<nz-form-label [nzSpan]="7" nzRequired>Username</nz-form-label>
<nz-form-control [nzSpan]="12" nzHasFeedback>
<input nz-input formControlName="userName" placeholder="async validate try to write JasonWood" />
<nz-form-explain
*ngIf="
(validateForm.get('userName')?.dirty && validateForm.get('userName')?.errors) ||
validateForm.get('userName')?.pending
"
>
<ng-container *ngIf="validateForm.get('userName')?.hasError('required')">
Please input your username!
</ng-container>
<ng-container *ngIf="validateForm.get('userName')?.hasError('duplicated')">
The username is redundant!
</ng-container>
<ng-container *ngIf="validateForm.get('userName')?.pending">
Validating...
</ng-container>
</nz-form-explain>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="7" nzRequired>E-mail</nz-form-label>
<nz-form-control [nzSpan]="12" nzHasFeedback>
<input nz-input formControlName="email" placeholder="email" type="email" />
<nz-form-explain *ngIf="validateForm.get('email')?.dirty && validateForm.get('email')?.errors">
<ng-container *ngIf="validateForm.get('email')?.hasError('email')">
The input is not valid E-mail!
</ng-container>
<ng-container *ngIf="validateForm.get('email')?.hasError('required')">
Please input your E-mail!
</ng-container>
</nz-form-explain>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="7" nzRequired>Password</nz-form-label>
<div>
<nz-form-control [nzSpan]="12" nzHasFeedback>
<input nz-input type="password" formControlName="password" (ngModelChange)="validateConfirmPassword()" />
<nz-form-explain
*ngIf="validateForm.get('password')?.dirty && validateForm.get('password')?.hasError('required')"
>Please input your password!</nz-form-explain
>
</nz-form-control>
</div>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="7" nzRequired>Confirm Password</nz-form-label>
<nz-form-control [nzSpan]="12" nzHasFeedback>
<input nz-input type="password" formControlName="confirm" placeholder="confirm your password" />
<nz-form-explain *ngIf="validateForm.get('confirm')?.dirty && validateForm.get('confirm')?.errors">
<ng-container *ngIf="validateForm.get('confirm')?.hasError('required')">
Please confirm your password!
</ng-container>
<ng-container *ngIf="validateForm.get('confirm')?.hasError('confirm')">
Password is inconsistent!
</ng-container>
</nz-form-explain>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="7" nzRequired>Comment</nz-form-label>
<nz-form-control [nzSpan]="12">
<textarea formControlName="comment" nz-input rows="2" placeholder="write any thing"></textarea>
<nz-form-explain
*ngIf="validateForm.get('comment')?.dirty && validateForm.get('comment')?.hasError('required')"
>Please write something here!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzOffset]="7" [nzSpan]="12">
<button nz-button nzType="primary" [disabled]="!validateForm.valid">Submit</button>
<button nz-button (click)="resetForm($event)">Reset</button>
</nz-form-control>
</nz-form-item>
</form>
`,
styles: [
`
[nz-form] {
max-width: 600px;
}
button {
margin-left: 8px;
}
`
]
})
export class NzDemoFormValidateReactiveComponent {
validateForm: FormGroup;
submitForm = ($event: any, value: any) => {
$event.preventDefault();
for (const key in this.validateForm.controls) {
this.validateForm.controls[key].markAsDirty();
this.validateForm.controls[key].updateValueAndValidity();
}
console.log(value);
};
resetForm(e: MouseEvent): void {
e.preventDefault();
this.validateForm.reset();
for (const key in this.validateForm.controls) {
this.validateForm.controls[key].markAsPristine();
this.validateForm.controls[key].updateValueAndValidity();
}
}
validateConfirmPassword(): void {
setTimeout(() => this.validateForm.controls.confirm.updateValueAndValidity());
}
userNameAsyncValidator = (control: FormControl) =>
new Observable((observer: Observer<ValidationErrors | null>) => {
setTimeout(() => {
if (control.value === 'JasonWood') {
observer.next({ error: true, duplicated: true });
} else {
observer.next(null);
}
observer.complete();
}, 1000);
});
confirmValidator = (control: FormControl): { [s: string]: boolean } => {
if (!control.value) {
return { required: true };
} else if (control.value !== this.validateForm.controls.password.value) {
return { confirm: true, error: true };
}
return {};
};
constructor(private fb: FormBuilder) {
this.validateForm = this.fb.group({
userName: ['', [Validators.required], [this.userNameAsyncValidator]],
email: ['', [Validators.email, Validators.required]],
password: ['', [Validators.required]],
confirm: ['', [this.confirmValidator]],
comment: ['', [Validators.required]]
});
}
}
模板驱动表单验证
我们在 nz-form-control
上 提供了 nzValidateStatus
nzHasFeedback
等属性,当使用模板驱动表单时,可以自己定义校验的时机和内容。
nzValidateStatus
: 校验状态,可选 'success', 'warning', 'error', 'validating'。nzHasFeedback
:用于给输入框添加反馈图标。nz-form-explain
:设置校验文案。
import { Component } from '@angular/core';
@Component({
selector: 'nz-demo-form-validate-static',
template: `
<form nz-form>
<nz-form-item>
<nz-form-label [nzSpan]="5">Fail</nz-form-label>
<nz-form-control nzValidateStatus="error" [nzSpan]="12">
<input nz-input [ngModel]="'unavailable choice'" name="errorValid" />
<nz-form-explain>Should be combination of numbers & alphabets</nz-form-explain>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5">Warning</nz-form-label>
<nz-form-control nzValidateStatus="warning" [nzSpan]="12">
<input nz-input [ngModel]="'Warning'" name="warningValid" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5">Validating</nz-form-label>
<nz-form-control [nzSpan]="12" nzValidateStatus="validating" nzHasFeedback>
<input nz-input [ngModel]="'The content is being validated'" name="validating" />
<nz-form-explain>I'm validating the content</nz-form-explain>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5">Success</nz-form-label>
<nz-form-control [nzSpan]="12" nzValidateStatus="success" nzHasFeedback>
<input nz-input [ngModel]="'The content'" name="successValid" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5">Warning</nz-form-label>
<nz-form-control [nzSpan]="12" nzValidateStatus="warning" nzHasFeedback>
<input nz-input [ngModel]="'Warning'" name="warningHighValid" />
<nz-form-explain>Should be combination of numbers & alphabets</nz-form-explain>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5">Fail</nz-form-label>
<nz-form-control [nzSpan]="12" nzValidateStatus="error" nzHasFeedback>
<input nz-input [ngModel]="'unavailable choice'" name="invalidValid" />
<nz-form-explain>Should be combination of numbers & alphabets</nz-form-explain>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5">Success</nz-form-label>
<nz-form-control [nzSpan]="12" nzValidateStatus="success" nzHasFeedback>
<nz-date-picker name="date-picker-success" style="width: 100%"></nz-date-picker>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5">Warning</nz-form-label>
<nz-form-control [nzSpan]="12" nzValidateStatus="warning" nzHasFeedback>
<nz-time-picker name="time-picker-warning" style="width: 100%"></nz-time-picker>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5">Error</nz-form-label>
<nz-form-control [nzSpan]="12" nzValidateStatus="error" nzHasFeedback>
<nz-select name="select-error" [ngModel]="'Option 1'">
<nz-option nzValue="Option 1" nzLabel="Option 1"></nz-option>
<nz-option nzValue="Option 2" nzLabel="Option 2"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5">Validating</nz-form-label>
<nz-form-control [nzSpan]="12" nzValidateStatus="validating" nzHasFeedback>
<nz-select name="select-validate" [ngModel]="'Option 2'">
<nz-option nzValue="Option 1" nzLabel="Option 1"></nz-option>
<nz-option nzValue="Option 2" nzLabel="Option 2"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5">Success</nz-form-label>
<nz-form-control [nzSpan]="12" nzValidateStatus="success" nzHasFeedback>
<nz-input-number name="inputnumber-success" style="width:100%"></nz-input-number>
</nz-form-control>
</nz-form-item>
</form>
`,
styles: [
`
[nz-form] {
max-width: 600px;
}
nz-date-picker ::ng-deep .ant-calendar-picker {
width: 100%;
}
`
]
})
export class NzDemoFormValidateStaticComponent {}
表单联动
使用 setValue
来动态设置其他控件的值。
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'nz-demo-form-coordinated',
template: `
<form nz-form [formGroup]="validateForm" (ngSubmit)="submitForm()">
<nz-form-item>
<nz-form-label [nzSpan]="5" nzRequired nzFor="note">Note</nz-form-label>
<nz-form-control [nzSpan]="12">
<input id="note" type="text" nz-input formControlName="note" />
<nz-form-explain *ngIf="validateForm.get('note')?.dirty && validateForm.get('note')?.errors"
>Please input your username!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="5" nzFor="gender" nzRequired>Gender</nz-form-label>
<nz-form-control [nzSpan]="12">
<nz-select
id="gender"
formControlName="gender"
nzPlaceHolder="Select a option and change input text above"
(ngModelChange)="genderChange($event)"
>
<nz-option nzValue="male" nzLabel="male"></nz-option>
<nz-option nzValue="female" nzLabel="female"></nz-option>
</nz-select>
<nz-form-explain *ngIf="validateForm.get('gender')?.dirty && validateForm.get('gender')?.errors"
>Please select your gender!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzSpan]="12" [nzOffset]="5">
<button nz-button nzType="primary">Submit</button>
</nz-form-control>
</nz-form-item>
</form>
`,
styles: [
`
[nz-form] {
max-width: 600px;
}
`
]
})
export class NzDemoFormCoordinatedComponent implements OnInit {
validateForm: FormGroup;
submitForm(): void {
for (const i in this.validateForm.controls) {
this.validateForm.controls[i].markAsDirty();
this.validateForm.controls[i].updateValueAndValidity();
}
}
genderChange(value: string): void {
this.validateForm.get('note')!.setValue(value === 'male' ? 'Hi, man!' : 'Hi, lady!');
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.validateForm = this.fb.group({
note: [null, [Validators.required]],
gender: [null, [Validators.required]]
});
}
}
表单布局
表单有三种布局。
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'nz-demo-form-layout',
template: `
<form
nz-form
[nzLayout]="validateForm.get('formLayout')?.value"
[formGroup]="validateForm"
(ngSubmit)="submitForm()"
>
<nz-form-item>
<nz-form-label [nzSpan]="isHorizontal ? 4 : null">Form Layout</nz-form-label>
<nz-form-control [nzSpan]="isHorizontal ? 14 : null">
<nz-radio-group formControlName="formLayout">
<label nz-radio-button [nzValue]="'horizontal'">Horizontal</label>
<label nz-radio-button [nzValue]="'vertical'">Vertical</label>
<label nz-radio-button [nzValue]="'inline'">Inline</label>
</nz-radio-group>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="isHorizontal ? 4 : null">Field A</nz-form-label>
<nz-form-control [nzSpan]="isHorizontal ? 14 : null">
<input nz-input formControlName="fieldA" placeholder="input placeholder" />
<nz-form-explain *ngIf="validateForm.get('fieldA')?.dirty && validateForm.get('fieldA')?.errors"
>Please input your username!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="isHorizontal ? 4 : null">Field B</nz-form-label>
<nz-form-control [nzSpan]="isHorizontal ? 14 : null">
<input nz-input formControlName="filedB" placeholder="input placeholder" />
<nz-form-explain *ngIf="validateForm.get('filedB')?.dirty && validateForm.get('filedB')?.errors"
>Please input your Password!</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzSpan]="isHorizontal ? 14 : null" [nzOffset]="isHorizontal ? 4 : null">
<button nz-button nzType="primary">Submit</button>
</nz-form-control>
</nz-form-item>
</form>
`,
styles: [
`
[nz-form]:not(.ant-form-inline):not(.ant-form-vertical) {
max-width: 600px;
}
`
]
})
export class NzDemoFormLayoutComponent implements OnInit {
validateForm: FormGroup;
submitForm(): void {
for (const i in this.validateForm.controls) {
this.validateForm.controls[i].markAsDirty();
this.validateForm.controls[i].updateValueAndValidity();
}
}
get isHorizontal(): boolean {
return this.validateForm.controls.formLayout && this.validateForm.controls.formLayout.value === 'horizontal';
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.validateForm = this.fb.group({
formLayout: ['horizontal'],
fieldA: [null, [Validators.required]],
filedB: [null, [Validators.required]]
});
}
}
动态校验规则
根据不同情况执行不同的校验规则。
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'nz-demo-form-dynamic-rule',
template: `
<form nz-form [formGroup]="validateForm" (ngSubmit)="submitForm()">
<nz-form-item>
<nz-form-label [nzSpan]="4" nzRequired nzFor="name">Name</nz-form-label>
<nz-form-control [nzSpan]="8">
<input type="text" nz-input formControlName="name" placeholder="Please input your name" />
<nz-form-explain *ngIf="validateForm.get('name')?.dirty && validateForm.get('name')?.errors"
>Please input your name</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="4" nzFor="nickname" [nzRequired]="validateForm.get('required')?.value"
>Nickname</nz-form-label
>
<nz-form-control [nzSpan]="8">
<input type="text" nz-input formControlName="nickname" placeholder="Please input your nickname" />
<nz-form-explain *ngIf="validateForm.get('nickname')?.dirty && validateForm.get('nickname')?.errors"
>Please input your nickname</nz-form-explain
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzSpan]="8" [nzOffset]="4">
<label nz-checkbox formControlName="required" (ngModelChange)="requiredChange($event)"
>Nickname is required</label
>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzSpan]="8" [nzOffset]="4">
<button nz-button nzType="primary">Check</button>
</nz-form-control>
</nz-form-item>
</form>
`
})
export class NzDemoFormDynamicRuleComponent implements OnInit {
validateForm: FormGroup;
submitForm(): void {
for (const i in this.validateForm.controls) {
this.validateForm.controls[i].markAsDirty();
this.validateForm.controls[i].updateValueAndValidity();
}
}
requiredChange(required: boolean): void {
if (!required) {
this.validateForm.get('nickname')!.clearValidators();
this.validateForm.get('nickname')!.markAsPristine();
} else {
this.validateForm.get('nickname')!.setValidators(Validators.required);
this.validateForm.get('nickname')!.markAsDirty();
}
this.validateForm.get('nickname')!.updateValueAndValidity();
}
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.validateForm = this.fb.group({
name: [null, [Validators.required]],
nickname: [null],
required: [false]
});
}
}
API
单独引入此组件
想要了解更多关于单独引入组件的内容,可以在快速上手页面进行查看。
import { NzFormModule } from 'ng-zorro-antd';
nz-formcomponent
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
[nzLayout] | 表单布局 | 'horizontal'|'vertical'|'inline' | 'horizontal' |
[nzNoColon] | 配置 nz-form-label 的 [nzNoColon] 的默认值 | boolean | false |
nz-form-itemcomponent
表单项用于区分表单中不同的区域,包含表单域和表单标签(可选)。
所有 nz-row 的参数在
nz-form-item
上均可直接使用。
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
[nzFlex] | 是否Flex布局 | boolean | false |
nz-form-labelcomponent
用于标示当前表单项的内容,可选。
所有 nz-col 的参数在
nz-form-label
上均可直接使用。
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
[nzRequired] | 当前项是否为必填,仅影响样式 | boolean | false |
[nzNoColon] | 是否不显示 label 后面的冒号 | boolean | false |
[nzFor] | label 标签的 for 属性 | string | - |
[nzColon] | 配合 label 属性使用,表示是否显示 label 后面的冒号 | boolean | true |
nz-form-controlcomponent
注意:由于 Angular Form 目前提供的状态变更订阅不完整。手动更改表单状态时,例如
markAsDirty
后,需要执行updateValueAndValidity
通知nz-form-control
进行状态变更。
表单一定会包含表单域,表单域可以是输入控件,标准表单域,标签,下拉菜单,文本域等。
所有 nz-col 的参数在
nz-form-control
上均可直接使用。
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
[nzValidateStatus] | Reactive Forms:会根据 FormControl 的状态自动生成校验状态 | FormControl | nz-form-control 中包裹的第一个 FormControl |
[nzValidateStatus] | Template-driven Forms:校验状态 | 'success'|'warning'|'error'|'validating' | - |
[nzHasFeedback] | 配合 nzValidateStatus 属性使用,展示校验状态图标 | boolean | false |
从 7.3.0 版本开始,nz-form-control
提供了 status
变量用于指示校验状态,status
会自动根据 [nzValidateStatus]
在 'success'|'warning'|'error'|'validating'
中自动切换,用户可以通过模板变量导出 status
用于切换提示信息。
nz-form-explaincomponent
用于显示提示信息,会自动根据当前的 nzValidateStatus 显示不同的颜色
注意:每个
nz-form-item
下最多只能有一个nz-form-explain
。
nz-form-extracomponent
用于显示表单额外提示信息
nz-form-splitcomponent
用于显示分隔符 -
nz-form-textcomponent
在 nz-form-control
中直接显示文本