Brian F Love
Learn from a Google Developer Expert focused on Angular, Web Technologies, and Node.js from Portland, OR.
Ad ·ultimatecourses.com
Learn Angular the right way with Ultimate Courses

Dynamic FormGroup Custom Validation in Angular2

In this post I will show you how to create nested FormGroups to create a custom validator.这适用于相关表单输入,例如复选框。如果您是Angular 2的新表格,请退房Thoughtram's post on reactive forms- it's a good read.

开始

To review Angular 2 has both model-driven forms as well as template-driven forms. I am using the model-driven reactive form. As such, I have imported the necessary classes from the @angular/forms module.

import{FormBuilder,FormControl,FormGroup,ReactiveFormsModule,验证器}"@angular/forms"

I have imported theFormBuilder,FormControl,FormGroup验证器课程。快速概述以下内容:

  • FormBuilder- this enables us to use some short-hand syntax for creating ourFormGroups.
  • FormControl- 这代表单个控制(或HTMLFormElement).
  • FormGroup- this represents a group of form fields. We will also use theFormGroupDirective在我们看来。
  • 验证器- 此类提供了我们的表单控件使用的一些内置验证器。

Form Template

Before we get to the form template, I want to create an array of days of the week and store this as a public variable in my component. This is only because I am going to use the name and values when creating the checkboxes in my form. You could simply create the necessary输入[type =“checkbox”]elements in your template instead.

interfaceIDay{name:string;:string;}@Component({})exportclassUpdateComponentimplementsngOnInit{上市天s:IDay[]=[{:"sunday",name:“星期日”},{:"monday",name:"Monday"},{:"tuesday",name:"Tuesday"},{:"wednesday",name:"Wednesday"},{:"thursday",name:"Thursday"},{:"friday",name:"Friday"},{:"saturday",name:"Saturday"},];}

Now, let's look at the form template:

<form[formGroup]="detailsForm"novalidate><inputtype="text"[formControl]="detailsForm.get('name')"[class.invalid]="!detailsForm.controls.name.valid"><divformGroupName="天s"><p* Ngfor.="让日子"><inputtype="checkbox"[formControlName]="Day.Value."[class.invalid]="!detailsForm.controls.days.valid"><label>{{day.name}}label>div>div>form>

A couple of things to note:

  • 该form uses theFormGroupDirective指定FormGroup我的控制器中的变量。
  • Next, I have create a simple text input field. I bind the formControl directive to the "name"FormControlinstance in mydetailsForm。I am also going to add the "invalid" class when the value is not valid. This field will be required.
  • Next, I have created anotherFormGroup, this is within thedetailsForm并被称为天s。This is defined using theFormGroupNamedirective.
  • Within the天sFormGroupI am looping over the array ofIDay物体使用的NgFordirective.
  • Each checkbox input is wrapped in a paragraph.
  • 该checkbox input uses theFormControlNamedirective to bind to thestring value within theIDay目的。I have also specified a class of "invalid" that will be applied to each checkbox input when群组是无效的。
  • 最后,I have a

Building aFormGroup

Back to our controller, we now need to create ourFormGroup变量命名detailsForm。该detailsFormwill contain all of the details about theFormControls, any nestedFormGroups,及其FormControls.

@Component({})exportclassUpdateComponentimplementsngOnInit{上市detailsForm:FormGroup;constructor(privateformBuilder:FormBuilder){}上市ngOnInit(){//create daysFormGroup using FormGroup long-hand syntax//this is so I can create a dynamic form from the array of IDay objectslet天sFormGroup:FormGroup=FormGroup({});for(letthis天s){let控制:FormControl=FormControl(,验证器required);天sFormGroupaddControl(,控制);}//create detailsForm FormGroup using FormBuilder's short-hand syntaxthisdetailsForm=thisformBuilder({name:["",验证器required],天s:天sFormGroup});}}

Let's walk through this:

  • First, I define thedetailsForm上市variable that is of typeFormGroup
  • 在我的构造函数中,我注射了FormBuilder。ThisFormBuilderwill be available as a private variable in my class. I will use this later to use theFormBuilder.group()short-hand syntax for creating aFormGroup
  • In myngOnInit方法我创建一个天sFormGroupvariable so that I can dynamically create theFormControl基于天sdefined. I could have easily hard-coded these controls, as well as the checkbox inputs in my template. In this example I also wanted to show the ability to use dynamic forms in Angular 2.
  • Next, I create thedetailsFormFormGroup使用FormBuilder。First, I have thenametext input, which uses therequiredmethod in the验证器class to require a value. Then, I define the daysFormGroup

Create Custom Validator for FormGroup

现在我们可以为此创建我们的自定义验证器Daysofweek.FormGroup。I am going to create a new private method in myUpdateComponentnamedvalidatedays()。This method will be passed theFormGroup

/** * Validate the days checkboxes. At least one must be selected. * * @class UpdateComponent * @method validateDays * @return {null|Object} Null if valid. */privatevalidateDays(formGroup:FormGroup){for(letkeyinformGroup控制s){if(formGroup控制shasownproperty.(key)){let控制:FormControl=<FormControl>formGroup控制s[key];if(控制){return空值;}}}return{validateDays:{valid:false}};}

validateDaysmethod loops over each control in theFormGroup和checks if the control has a value. If any of the control's have a value, then the method returns null - theFormGroup已验证。否则,我们返回一个指定的对象validateDays验证器无效。

该last thing we need to do is tell our天sFormGroupinstance that we have a validator. So, let's modify ourngOnInit()method:

@Component({})exportclassUpdateComponentimplementsngOnInit{上市ngOnInit(){//create daysFormGroup using FormGroup long-hand syntax//this is so I can create a dynamic form from the array of IDay objectslet天sFormGroup:FormGroup=FormGroup({},(formGroup:FormGroup)=>{returnthisvalidateDays(formGroup);});}}

I am now specifying the validator function for theFormGroup。Unfortunately, it doesn't look like there is a way to set the validator after creating theFormGroupinstance.

Using FormBuilder

You can also set the validator when usingFormBuilder使用following syntax:

@Component({})exportclassUpdateComponentimplementsngOnInit{上市ngOnInit(){//create detailsForm FormGroup using FormBuilder's short-hand syntaxthisdetailsForm=thisformBuilder({name:["",验证器required],天s:thisformBuilder({sunday:false,monday:false,星期二:false,wednesday:false,thursday:false,星期五:false,saturday:false},{validator:(formGroup:FormGroup)=>{returnthisvalidateDays(formGroup);}})});}}

In this example I am not dynamically creating myFormGroup, rather I have specified each control in my form (each day of the week). I then pass in the extras object as the second argument, which has a property namedvalidator, which is my validator function. I am using TypeScript's fat arrow function to bind the scope of the anonymous function to the class'sthis范围。

Brian F Love

Hi, I'm Brian. I am interested in TypeScript, Angular and Node.js. I'm married to my best friend Bonnie, I live in Portland and I ski (a lot).