Form

Form is used to collect, validate, and submit the user input, usually contains various form items including checkbox, radio, input, select, and etc.

Form is totally based on Angular Forms, you can use reactive forms or template-driven-forms.

Please make sure you have read the official form document before using the component.

Form#

You can align the controls of a form using the layout prop:

  • horizontal:to horizontally align the labels and controls of the fields. (Default)
  • vertical:to vertically align the labels and controls of the fields.
  • inline:to render form fields in one line.

nz-form-item#

Used to separate the item in forms, contains label(optional) and control field.

nz-form-label#

The label of the form item, optional.

nz-form-control#

A form consists of one or more form fields whose type includes input, textarea, checkbox, radio, select, tag, and more.

<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>

Examples

Horizontal login form is often used in navigation bar.

expand codeexpand code
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]
    });
  }
}

Normal login form which can contain more elements.

expand codeexpand code
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]
    });
  }
}
+86
We must make sure that your are a human.

Fill in this form to create a new account for you.

expand codeexpand code
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]
    });
  }
}

Add or remove form items dynamically.

expand codeexpand code
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();
  }
}

We provide properties like nzValidateStatusnzHasFeedback in nz-form-control to customize your own validate status and message, when using reactive forms.

  1. nzValidateStatus: validate status of form components, the default status comes from the NgControl in nz-form-control, you can set other NgControl to it.
  2. nzHasFeedback: display feed icon of input control
  3. nz-form-explain: display validate message.
expand codeexpand code
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]]
    });
  }
}
Should be combination of numbers & alphabets
I'm validating the content
Should be combination of numbers & alphabets
Should be combination of numbers & alphabets
Option 1
Option 2

We provide properties like nzValidateStatusnzHasFeedback in nz-form-control to customize your own validate status and message, when using template-driven forms.

  1. nzValidateStatus: validate status of form components which could be 'success', 'warning', 'error', 'validating'.
  2. nzHasFeedback: display feed icon of input control
  3. nz-form-explain: display validate message.
expand codeexpand code
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 {}
Select a option and change input text above

Use setValue to set other control's value programmaticly.

expand codeexpand code
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]]
    });
  }
}

There are three layout for form: horizontal, vertical, inline.

expand codeexpand code
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]]
    });
  }
}

Perform different check rules according to different situations.

expand codeexpand code
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 this Component Individually#

You can get more detail here.

import { NzFormModule } from 'ng-zorro-antd';

nz-form#

PropertyDescriptionTypeDefault Value
[nzLayout]Form layout'horizontal'|'vertical'|'inline''horizontal'
[nzNoColon]change default props [nzNoColon] value of nz-form-labelbooleanfalse

nz-form-item#

Used to separate the item in forms, contains label(optional) and control field.

All api in nz-row can be used in nz-form-item.

PropertyDescriptionTypeDefault Value
[nzFlex]display flexbooleanfalse

nz-form-label#

The label of the form item, optional.

All api in nz-col can be used in nz-form-label.

PropertyDescriptionTypeDefault Value
[nzRequired]add required style to current itembooleanfalse
[nzNoColon]whether to not display : after label text.booleanfalse
[nzFor]The for property of labelstring-
[nzColon]Used with label, whether to display : after label text.booleantrue

nz-form-control#

Note:Due to the lack of partial Observable in Angular Form, you have to notify nz-form-control to update its status with updateValueAndValidity when you update form status using methods like markAsDirty.

A form consists of one or more form fields whose type includes input, textarea, checkbox, radio, select, tag, and more.

All api in nz-col can be used in nz-form-control.

PropertyDescriptionTypeDefault Value
[nzValidateStatus]Reactive Forms: Will generate status based on FormControlFormControlfirst FormControl in nz-form-control
[nzValidateStatus]Template-driven Forms: The validation status'success'|'warning'|'error'|'validating'-
[nzHasFeedback]Used with nzValidateStatus, this option specifies the validation status icon. Recommended to be used only with Input.booleanfalse

From 7.3.0 version, nz-form-control provide status variable, it will switch between 'success'|'warning'|'error'|'validating' automatically according to [nzValidateStatus] passed in, user can get it from template reference variables.

nz-form-explain#

Validation messages

nz-form-extra#

The extra prompt message. It is similar to help.

nz-form-split#

The split icon of -

nz-form-text#

Text in nz-form-control