How to Prevent Infinite Calls to Angular Getter Methods in Form Validation?

Discussão em 'Angular' iniciado por Ravi Gaud, Janeiro 12, 2025.

  1. Ravi Gaud

    Ravi Gaud Guest

    I'm currently facing an issue with infinite calls to a getter method in my Angular component that handles form validation. The getter is used to determine the validity of a form control, but it seems to be causing an infinite loop due to Angular's change detection mechanism.

    text-input.component.ts


    import { CommonModule } from '@angular/common';
    import { IonLabel, IonInput } from '@ionic/angular/standalone';
    import { Component, inject, Input, OnDestroy, OnInit } from '@angular/core';
    import { ControlContainer, FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';

    @Component({
    standalone: true,
    selector: 'app-text-input',
    imports: [ReactiveFormsModule, IonLabel, IonInput, CommonModule],
    viewProviders: [
    {
    provide: ControlContainer,
    useFactory: () => inject(ControlContainer, { skipSelf: true }),
    },
    ],
    template: `
    <div class="input-section ion-padding-top">
    <!-- label -->
    <ion-label class="input-label">
    {{ label }}
    @if (required) {
    <span class="required-star">*</span>
    }
    </ion-label>

    <!-- input -->
    <ion-input
    mode="md"
    fill="outline"
    [ngClass]="inputClass"
    [placeholder]="placeholderText"
    [formControlName]="controlName"
    />

    <!-- validation -->
    @if (isControlInvalid) {
    <ion-label class="invalid-label">Please enter the {{ label.toLowerCase() }}.</ion-label>
    }
    </div>
    `,
    })
    export class TextInputComponent implements OnInit, OnDestroy {
    @Input() required = true;
    @Input() formSubmitted = false;
    @Input({ required: true }) label = '';
    @Input({ required: true }) controlName = '';
    @Input({ required: true }) placeholderText = '';

    constructor(
    private formBuilder: FormBuilder,
    private parentContainer: ControlContainer,
    ) {}

    get parentFormGroup() {
    return this.parentContainer.control as FormGroup;
    }

    // Getter to check if the control is invalid
    get isControlInvalid() {
    console.log('called 1');
    return this.formSubmitted && this.parentFormGroup.get(this.controlName)?.invalid;
    }

    // Getter to get the input class
    get inputClass() {
    console.log('called 2');
    return this.isControlInvalid ? 'invalid-input' : 'valid-input';
    }

    ngOnInit() {
    this.parentFormGroup.addControl(this.controlName, this.formBuilder.control('', Validators.required));
    }

    ngOnDestroy() {
    this.parentFormGroup.removeControl(this.controlName);
    }
    }

    parent.component.ts


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

    @Component({
    selector: 'app-parent',
    templateUrl: './parent.component.html',
    })
    export class ParentComponent implements OnInit {
    eventForm!: FormGroup;
    formSubmitted: boolean = false;

    constructor(private fb: FormBuilder) {}

    ngOnInit() {
    // automatically add the location when call the app-text-input component
    this.eventForm = this.fb.group({});
    }
    }

    parent.component.html


    <form [formGroup]="eventForm">
    <app-text-input
    label="Venue"
    controlName="location"
    [formSubmitted]="formSubmitted"
    placeholderText="Venue Name" />
    </form>


    [​IMG]

    What strategies can I implement to prevent infinite calls to the getter method? Are there best practices for managing state in Angular reactive forms that could help in this situation?

    Continue reading...

Compartilhe esta Página