0

I have following template for input fields in multiple forms (please ignore objToKeys - it is custom pipe and it works) :

<div [formGroup]="form">
  <ion-item>
    <ion-label color="primary" position="floating">{{ label }}</ion-label>

    <ion-input type="text" formControlName="{{ controlName }}"></ion-input>
  </ion-item>

  <div *ngIf="form.controls[controlName].touched && form.controls[controlName].errors" class="form-error-messages">
    <div *ngFor="let key of form.controls[controlName].errors | objToKeys">
      <ion-icon color="danger" name="alert-outline"></ion-icon>
      <ion-label class="ion-padding-start" color="danger" class="ion-align-items-end">
        {{ form.controls[controlName].errors[key].message }}
      </ion-label>
    </div>
  </div>
</div>

I tried to get this template simplified by creating a custom component : component.ts

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

@Component({
  selector: 'app-form-input',
  templateUrl: './form-input.component.html',
  styleUrls: ['./form-input.component.scss'],
})
export class FormInputComponent implements OnInit {
  @Input() label: string;
  @Input() controlName: string;
  @Input() form: FormGroup;
  constructor() {}

  ngOnInit() {}
}

component.html

<div [formGroup]="form">
  <ion-item>
    <ion-label color="primary" position="floating">{{ label }}</ion-label>
    <ion-input type="text" formControlName="{{ controlName }}"></ion-input>
  </ion-item>
  <div *ngIf="form.controls.name.touched && form.controls.name.errors" class="form-error-messages">
    <div *ngFor="let key of form.controls.name.errors | objToKeys">
      <ion-icon color="danger" name="alert-outline"></ion-icon>
      <ion-label class="ion-padding-start" color="danger" class="ion-align-items-end">
        {{ form.controls.name.errors[key].message }}
      </ion-label>
    </div>
  </div>
</div>

Please note that in the above html, the input is wrapped in a div with [formGroup]="form". I I do not wrap it then Angular complains that the formControl is not enclosed inside the formgroup. However note that the parent component that calls it, has the [formGroup] attribute.

<form [formGroup]="form" (ngSubmit)="onSubmit()" #formRef="ngForm">
  <app-form-input [label]="'Insitution Name'" [controlName]="'name'" [form]="form"></app-form-input>


  <app-actions
    slot="end"
    [itemType]="'summary'"
    [actionMode]="'answer'"
    [formMode]="formMode"
    (saveSummary)="submitForm()"
    (cancelSummary)="onCancel()"
  ></app-actions>
</form>

So why was angular complaining initially, is my solution correct? Is this a good way to achieve component reuse?

3
  • This is not the correct way. It gives problems with Angular change detection cycle Commented May 4, 2020 at 20:48
  • Still trying to debug Commented May 4, 2020 at 20:48
  • this is the same question : stackoverflow.com/questions/60200533/… Commented May 4, 2020 at 20:56

1 Answer 1

0

There are several questions on the same topic. I posted one in the link.Do an exhaustive search on this site. Apparently it is a common error.

My Solution was based on this blog by Netanel Basal:

I changed the ChangeDetectionStarategy on the parent component to : changeDetection: ChangeDetectionStrategy.OnPush,

This change got rid of the error:

Expression has changed after it was checked. Previous value: 'ng-valid: true'. Current value: 'ng-valid: false'

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.