I would like to pass the parent component's FormGroup
to its child for the purpose of displaying an error-message using the child.
Given the following parent:
parent.component.ts
import { Component, OnInit } from '@angular/core' import { REACTIVE_FORM_DIRECTIVES, AbstractControl, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms' @Component({ moduleId: module.id, selector: 'parent-cmp', templateUrl: 'language.component.html', styleUrls: ['language.component.css'], directives: [ErrorMessagesComponent] }) export class ParentCmp implements OnInit { form: FormGroup; first: AbstractControl; second: AbstractControl; constructor(private _fb: FormBuilder) { this.first = new FormControl(''); this.second = new FormControl('') } ngOnInit() { this.form = this._fb.group({ 'first': this.first, 'second': this.second }); } }
I would now like to pass the form:FormGroup variable above to the child component below:
error-message.component.ts
import { Component, OnInit, Input } from '@angular/core' import { NgIf } from '@angular/common' import {REACTIVE_FORM_DIRECTIVES, FormGroup } from '@angular/forms' @Component({ moduleId: module.id, selector: 'epimss-error-messages', template: `<span class="error" *ngIf="errorMessage !== null">{{errorMessage}}</span>`, styles: [], directives: [REACTIVE_FORM_DIRECTIVES, NgIf] }) export class ErrorMessagesComponent implements OnInit { @Input() ctrlName: string constructor(private _form: FormGroup) { } ngOnInit() { } get errorMessage() { // Find the control in the Host (Parent) form let ctrl = this._form.find(this.ctrlName); console.log('ctrl| ', ctrl); // for (let propertyName of ctrl.errors) { // // If control has a error // if (ctrl.errors.hasOwnProperty(propertyName) && ctrl.touched) { // // Return the appropriate error message from the Validation Service // return CustomValidators.getValidatorErrorMessage(propertyName); // } // } return null; }
The constructor formGroup represents the FormGroup of the parent - in its present form it does not work.
I am trying to follow this obsolete example at http://iterity.io/2016/05/01/angular/angular-2-forms-and-advanced-custom-validation/
@Input() and @Output() give a child component a way to communicate with its parent component. @Input() lets a parent component update data in the child component. Conversely, @Output() lets the child send data to a parent component.
In the parent component do this:
<div [formGroup]="form"> <div>Your parent controls here</div> <your-child-component [formGroup]="form"></your-child-component> </div>
And then in your child component you can get hold of that reference like so:
export class YourChildComponent implements OnInit { public form: FormGroup; // Let Angular inject the control container constructor(private controlContainer: ControlContainer) { } ngOnInit() { // Set our form property to the parent control // (i.e. FormGroup) that was passed to us, so that our // view can data bind to it this.form = <FormGroup>this.controlContainer.control; } }
You can even ensure either formGroupName
or [formGroup]
is specified on your component by changing its selector like so:
selector: '[formGroup] epimss-error-messages,[formGroupName] epimss-error-messages'
This answer should be sufficient for your needs, but if you want to know more I've written a blog entry here:
https://mrpmorris.blogspot.co.uk/2017/08/angular-composite-controls-formgroup-formgroupname-reactiveforms.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With