1
votes

I have a parent form component that is using a child form component. I am using Angular reactive forms. My validator functions are working correctly, but the issue is that when the form loads, the child form component is already marked as touched, which messes up my validator functions:

this.editUserForm = this.fb.group ({
  phone: ['123-456-1234'],
  fax: [null],
  email: [null],
  website: [null],
  editUserForm_Address : this.fb.group ({
    address1: ['123 Elm Street', Validators.required],
    address2: [null],
    city: ['Dummy City', Validators.required],
    state: ['Dummy State', Validators.required],
    zipcode: ['11111', Validators.required],
    country: ['USA', Validators.required]
  })
});

The parent component html uses the child component:

<form [formGroup] = "editUserForm">
<address-form formGroupName = "editUserForm_Address"></address-form>
</form>

The child component class is like:

export class AddressFormComponent implements OnInit {

  public addressFormGroup: FormGroup;

  @Input()

  constructor(private controlContainer: ControlContainer) { }

  ngOnInit() {
    this.addressFormGroup = <FormGroup>this.controlContainer.control;
  }

}

The child component html is like this (just Address 1 for an example):

   <ng-container [formGroup] = "addressFormGroup">   
    <div class = "row">
     <div class = "form-group col-12" [ngClass]="{'error': (addressFormGroup.controls['address1'].errors)">
       <label for="street" >Address 1*</label>
       <input placeholder = "Address 1" class="form-control" formControlName="address1">
       <div *ngIf="(addressFormGroup.controls['address1'].errors)" class="error-msg">
        <div [hidden]="!addressFormGroup.controls['address1'].errors.required"
 class = "input_feedback">Address 1 is required.</div>
       </div>
     </div>

What I've tried: I've tried using lifecycle hooks, such as ngAfterViewInit() to mark the child formGroup as untouched, but ngAfterViewInit() executes and then the form loads, with the child formGroup is still marked as touched.

1

1 Answers

1
votes

All you need to do, is to pass the formgroup to the child, and show that formgroup in the template. So just mark as @Input and that's it :)

<address-form 
  [editUserForm_Address]="editUserForm.get('editUserForm_Address')">
</address-form>

Then in child, just mark:

@Input() editUserForm_Address: FormGroup;

Also in template, I would suggest to utilize get() for formfield and hasError() to check errors on formgroup, makes template more readable in my opinion :)

<ng-container [formGroup]="editUserForm_Address">   
  <label for="street">Address 1*</label>
  <input placeholder="Address 1" formControlName="address1">
  <div *ngIf="editUserForm_Address.get('address1').errors">
    <div [hidden]="!editUserForm_Address.hasError('required','address1')">
      Address 1 is required.
    </div>
  </div>
</ng-container>

A sample StackBlitz