Brian F Love
Learn from a Google Developer Expert focused on Angular, Web Technologies, and Node.js from Portland, OR.
Ad ·
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.


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.


Now, let's look at the form template:

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