Home >Web Front-end >JS Tutorial >An introduction to responsive forms in Angular

An introduction to responsive forms in Angular

不言
不言Original
2018-07-11 14:57:201890browse

This article mainly introduces the introduction of responsive forms in Angular. It has a certain reference value. Now I share it with you. Friends in need can refer to it.

The responsive form is in the component class Write the logic, validation rules, unlike template-driven forms where control is done in the template. Reactive forms are flexible and can be used to handle any complex form scenario. We write more component code and less HTML code, making unit testing easier.

Form base and interface

Form base

<form novalidate>
  <label>
    <span>Full name</span>
    <input
      type="text"
      name="name"
      placeholder="Your full name">
  </label>
  <p>
    <label>
      <span>Email address</span>
      <input
        type="email"
        name="email"
        placeholder="Your email address">
    </label>
    <label>
      <span>Confirm address</span>
      <input
        type="email"
        name="confirm"
        placeholder="Confirm your email address">
    </label>
  </p>
  <button type="submit">Sign up</button>
</form>

The next functions we want to implement are as follows:

  • Bind name, Values ​​of email and confirm input boxes

  • Add form validation function to all input boxes

  • Display validation exception information

  • When form verification fails, form submission is not allowed

  • Form submission function

User interface

// signup.interface.ts
export interface User {
  name: string;
  account: {
    email: string;
    confirm: string;
  }
}

ngModule and reactive forms

Before we continue to introduce the reactive forms form in depth, we must import the ReactiveFormsModule in the @angular/forms library in @NgModule:

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    ...,
    ReactiveFormsModule
  ],
  declarations: [...],
  bootstrap: [...]
})
export class AppModule {}
Friendly reminder: If you use reactive forms, import ReactiveFormsModule; if template-driven forms are used, import FormsModule.

Reactive approach

We will create a SignupFormComponent based on the base form defined above:

signup-form.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'signup-form',
  template: `
    <form novalidate>...</form>
  `
})
export class SignupFormComponent {
  constructor() {}
}

This is a Basic components. Before we implement the above functions, we need to first introduce the concepts and uses of FormControl, FormGroup, and FormBuilder.

FormControl and FormGroup

Let’s first introduce the concepts of FormControl and FormGroup:

FormControl - It is a class that provides support for a single form control and can be used to track controls value and validation status, in addition to providing a series of public APIs.

Usage example:

ngOnInit() {
  this.myControl = new FormControl('');
}
FormGroup - Contains a set of FormControl instances that can be used to track the value and validation status of the FormControl group, and also provides a series of public APIs.

Usage example:

ngOnInit() {
  this.myGroup = new FormGroup({
    name: new FormControl(''),
    location: new FormControl('')
  });
}

Now that we have created FormControl and FormGroup instances, let’s take a look at how to use it:

<form novalidate [formGroup]="myGroup">
  Name: <input type="text" formControlName="name">
  Location: <input type="text" formControlName="location">
</form>

In the above example, we must use [ formGroup] binds the myGroup object we created. In addition, we also use the formControlName directive to bind the FormControl control we created. The form structure at this time is as follows:

FormGroup -> 'myGroup'
    FormControl -> 'name'
    FormControl -> 'location'

Implementing our FormGroup model

signup.interface.ts

export interface User {
  name: string;
  account: {
    email: string;
    confirm: string;
  }
}

The corresponding form structure is as follows:

FormGroup -> 'user'
    FormControl -> 'name'
    FormGroup -> 'account'
        FormControl -> 'email'
        FormControl -> 'confirm'

Yes, we can create nested FormGroup collections! Let's update the component (without the initial data):

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';

@Component({...})
export class SignupFormComponent implements OnInit {
  user: FormGroup;
  ngOnInit() {
    this.user = new FormGroup({
      name: new FormControl(''),
      account: new FormGroup({
        email: new FormControl(''),
        confirm: new FormControl('')
      })
    });
  }
}

If we want to set the initial data, we can do so as in the example above. Normally, we obtain the initial information of the form through the API interface provided by the server.

Binding our FormGroup model

Now that we have instantiated the FormGroup model, it is time to bind to the corresponding DOM element. Specific examples are as follows:

<form novalidate [formGroup]="user">
  <label>
    <span>Full name</span>
    <input
      type="text"
      placeholder="Your full name"
      formControlName="name">
  </label>
  <p formGroupName="account">
    <label>
      <span>Email address</span>
      <input
        type="email"
        placeholder="Your email address"
        formControlName="email">
    </label>
    <label>
      <span>Confirm address</span>
      <input
        type="email"
        placeholder="Confirm your email address"
        formControlName="confirm">
    </label>
  </p>
  <button type="submit">Sign up</button>
</form>

Now the associated information between the FormGroup and FormControl objects and the DOM structure is as follows:

// JavaScript APIs
FormGroup -> 'user'
    FormControl -> 'name'
    FormGroup -> 'account'
        FormControl -> 'email'
        FormControl -> 'confirm'

// DOM bindings
formGroup -> 'user'
    formControlName -> 'name'
    formGroupName -> 'account'
        formControlName -> 'email'
        formControlName -> 'confirm'

Reactive submit

Like the template-driven form, we can pass ngSubmit Output attributes, handle form submission logic:

<form novalidate (ngSubmit)="onSubmit()" [formGroup]="user">
  ...
</form>

Reactive error validation

Next we add validation rules to the form, first we need to import Validators from @angular/forms. Specific usage examples are as follows:

ngOnInit() {
  this.user = new FormGroup({
    name: new FormControl('', [Validators.required, Validators.minLength(2)]),
    account: new FormGroup({
      email: new FormControl('', Validators.required),
      confirm: new FormControl('', Validators.required)
    })
  });
}

Through the above examples, we can see that if the form control contains multiple validation rules, you can use an array to declare multiple validation rules. If you only include one validation rule, just declare it directly. This way, we don't need to add the required attribute to the input control in the template. Next, let's add the form submission function when the form verification fails:

<form novalidate (ngSubmit)="onSubmit(user)" [formGroup]="user">
  ...
  <button type="submit" [disabled]="user.invalid">Sign up</button>
</form>

Then the question is, how do we get the verification information of the form control? We can use the method introduced in template-driven forms, as follows:

<form novalidate [formGroup]="user">
  {{ user.controls.name?.errors | json }}
</form>

In addition, we can also use the API provided by the FormGroup object to obtain the error information of the form control validation:

<form novalidate [formGroup]="user">
  {{ user.get('name').errors | json }}
</form>

Now we Let’s take a look at the complete code:

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { User } from './signup.interface';

@Component({
  selector: 'signup-form',
  template: `
    <form novalidate (ngSubmit)="onSubmit(user)" [formGroup]="user">
      <label>
        <span>Full name</span>
        <input type="text" placeholder="Your full name" formControlName="name">
      </label>
      <p class="error" *ngIf="user.get(&#39;name&#39;).hasError(&#39;required&#39;) && 
            user.get(&#39;name&#39;).touched">
        Name is required
      </p>
      <p class="error" *ngIf="user.get(&#39;name&#39;).hasError(&#39;minlength&#39;) && 
            user.get(&#39;name&#39;).touched">
        Minimum of 2 characters
      </p>
      <p formGroupName="account">
        <label>
          <span>Email address</span>
          <input type="email" placeholder="Your email address" formControlName="email">
        </label>
        <p
          class="error"
          *ngIf="user.get(&#39;account&#39;).get(&#39;email&#39;).hasError(&#39;required&#39;) && 
             user.get(&#39;account&#39;).get(&#39;email&#39;).touched">
          Email is required
        </p>
        <label>
          <span>Confirm address</span>
          <input type="email" placeholder="Confirm your email address" 
             formControlName="confirm">
        </label>
        <p
          class="error"
          *ngIf="user.get(&#39;account&#39;).get(&#39;confirm&#39;).hasError(&#39;required&#39;) && 
             user.get(&#39;account&#39;).get(&#39;confirm&#39;).touched">
          Confirming email is required
        </p>
      </p>
      <button type="submit" [disabled]="user.invalid">Sign up</button>
    </form>
  `
})
export class SignupFormComponent implements OnInit {
  user: FormGroup;
  constructor() {}
  ngOnInit() {
    this.user = new FormGroup({
      name: new FormControl('', [Validators.required, Validators.minLength(2)]),
      account: new FormGroup({
        email: new FormControl('', Validators.required),
        confirm: new FormControl('', Validators.required)
      })
    });
  }
  onSubmit({ value, valid }: { value: User, valid: boolean }) {
    console.log(value, valid);
  }
}

The function is implemented, but the way to create a FormGroup object is a bit cumbersome. The Angular team is also aware of this, so it provides us with FormBuilder to simplify the above operations.

Simplifying with FormBuilder

First we need to import FormBuilder from @angular/forms:

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

export class SignupFormComponent implements OnInit {
  user: FormGroup;
  constructor(private fb: FormBuilder) {}
  ...
}

Then we use the group() method provided by the FormBuilder object to create the FormGroup and FormControl object:

Code before adjustment (without FormBuilder):

ngOnInit() {
  this.user = new FormGroup({
    name: new FormControl('', [Validators.required, Validators.minLength(2)]),
    account: new FormGroup({
      email: new FormControl('', Validators.required),
      confirm: new FormControl('', Validators.required)
    })
  });
}

Adjusted code (with FormBuilder):

ngOnInit() {
  this.user = this.fb.group({
    name: ['', [Validators.required, Validators.minLength(2)]],
    account: this.fb.group({
      email: ['', Validators.required],
      confirm: ['', Validators.required]
    })
  });
}

Compare the before and after adjustments Code, does it feel a lot more convenient all of a sudden? At this time, the complete code after the update is as follows:

@Component({...})
export class SignupFormComponent implements OnInit {
  user: FormGroup;
  constructor(private fb: FormBuilder) {}
  ngOnInit() {
    this.user = this.fb.group({
      name: ['', [Validators.required, Validators.minLength(2)]],
      account: this.fb.group({
        email: ['', Validators.required],
        confirm: ['', Validators.required]
      })
    });
  }
  onSubmit({ value, valid }: { value: User, valid: boolean }) {
    console.log(value, valid);
  }
}

The above is the entire content of this article. I hope it will be helpful to everyone's study. For more related content, please pay attention to the PHP Chinese website!

related suggestion:

The release content of art-dialog-vue2.0, a dialog plug-in based on vue.js

The difference between AngularJs and Angular’s ​​commonly used instructions

The above is the detailed content of An introduction to responsive forms in Angular. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn