How can i apply code before an element is erased by an *ngIf in Angular 13?

70 views Asked by At

I'm handling this form in which will be shown an input depending on the option that was selected

<form [formGroup]="form" (ngSubmit)="search()">
        <div class="row">
            <div class="col-4">
                <p-dropdown [options]="selectCriteria" (change)="optionIsSelected" placeholder="{{this.translate.data.selectSearchCriteria}}" [showClear]="true" formControlName="searchOption">
                </p-dropdown>
            </div>
            <div class="col-6">
                <div *ngIf="optionSelected=='Recruiter'" #inputOption>
                    <input pInputText type="text" [disabled]="!optionIsSelected" formControlName="recruiter">
                </div>
                <div *ngIf="optionSelected=='Code'" #inputOption> #codeInput>
                    <input pInputText type="number" [disabled]="!optionIsSelected" formControlName="codeRequest">
                </div>
            </div>
            <div class="col-2">
                <p-button *ngIf="!advancedSearch" type="submit" [label]="this.translate.data.search" [disabled]="form.invalid" class="col-2" icon="pi pi-search"></p-button>
            </div>
        </div>

I'm using this intricate handling method to deactivate the validation for one or another input depending on what option was selected

  ngOnInit(): void { 
    this.form.get("searchOption").valueChanges.subscribe((searchOption) => {
      if (searchOption === 1 && !this.advancedSearch) {
        this.form.markAsUntouched();
        this.optionSelected = "Code"
        this.optionIsSelected = true
        this.form.get("recruiter").setValue("");
        this.form.get("recruiter").clearValidators();
        this.form.get("recruiter").updateValueAndValidity();
        this.form
          .get("codeRequest")
          .setValidators([Validators.required, Validators.pattern(/^[0-9]*$/)]);
        this.form.get("codeRequest").updateValueAndValidity();
      } else if (searchOption === 2 && !this.advancedSearch) {
        this.form.markAsUntouched();
        this.optionSelected = "Recruiter"
        this.optionIsSelected = true
        this.form.get("codeRequest").setValue(null);
        this.form.get("codeRequest").clearValidators();
        this.form.get("codeRequest").updateValueAndValidity();
        this.form.get("recruiter").setValidators([Validators.required]);
        this.form.get("recruiter").updateValueAndValidity();
      } else {
        this.optionIsSelected = false
      }
    });
  }

But it came to me that this way of handling won't work, as the input object discared is destroyed before i can even discard it's validation, mantaining my view with a form error as it didn't discarded the validation before it was destroyed. I tried using ViewChild, but i didn't find an extension for a ViewChild or ViewChildren which subscribes or listens to the destruction of said children. Which way could i use to anticipate it's destruction, knowing that the elements are not components made by me but dropdowns of the PrimeNG framework?

I'm handling this form in which will be shown an input depending on the option that was selected

<form [formGroup]="form" (ngSubmit)="search()">
        <div class="row">
            <div class="col-4">
                <p-dropdown [options]="selectCriteria" (change)="optionIsSelected" placeholder="{{this.translate.data.selectSearchCriteria}}" [showClear]="true" formControlName="searchOption">
                </p-dropdown>
            </div>
            <div class="col-6">
                <div *ngIf="optionSelected=='Recruiter'" #inputOption>
                    <input pInputText type="text" [disabled]="!optionIsSelected" formControlName="recruiter">
                </div>
                <div *ngIf="optionSelected=='Code'" #inputOption> #codeInput>
                    <input pInputText type="number" [disabled]="!optionIsSelected" formControlName="codeRequest">
                </div>
            </div>
            <div class="col-2">
                <p-button *ngIf="!advancedSearch" type="submit" [label]="this.translate.data.search" [disabled]="form.invalid" class="col-2" icon="pi pi-search"></p-button>
            </div>
        </div>

I'm using this intricate handling method to deactivate the validation for one or another input depending on what option was selected

  ngOnInit(): void { 
    this.form.get("searchOption").valueChanges.subscribe((searchOption) => {
      if (searchOption === 1 && !this.advancedSearch) {
        this.form.markAsUntouched();
        this.optionSelected = "Code"
        this.optionIsSelected = true
        this.form.get("recruiter").setValue("");
        this.form.get("recruiter").clearValidators();
        this.form.get("recruiter").updateValueAndValidity();
        this.form
          .get("codeRequest")
          .setValidators([Validators.required, Validators.pattern(/^[0-9]*$/)]);
        this.form.get("codeRequest").updateValueAndValidity();
      } else if (searchOption === 2 && !this.advancedSearch) {
        this.form.markAsUntouched();
        this.optionSelected = "Recruiter"
        this.optionIsSelected = true
        this.form.get("codeRequest").setValue(null);
        this.form.get("codeRequest").clearValidators();
        this.form.get("codeRequest").updateValueAndValidity();
        this.form.get("recruiter").setValidators([Validators.required]);
        this.form.get("recruiter").updateValueAndValidity();
      } else {
        this.optionIsSelected = false
      }
    });
  }

But it came to me that this way of handling won't work, as the input object discared is destroyed before i can even discard it's validation, mantaining my view with a form error as it didn't discarded the validation before it was destroyed. I tried using ViewChild, but i didn't find an extension for a ViewChild or ViewChildren which subscribes or listens to the destruction of said children. Which way could i use to anticipate it's destruction, knowing that the elements are not components made by me but divs from html?

1

There are 1 answers

0
Dariusz81 On

Disabled FormControls are not validated (and their values are not returned when you read this.form.value so you just need to disable the options - no need to clearValidators just this.form.get("recruiter").disable() and you will be fine.

If you would like to read values of disabled FormControls you need to call this.form.getRawValue()

Don't use *ngIf="optionSelected=='Code'" - just hide the elements with CSS like [style.display]="optionSelected=='Code' ? 'block' : 'none'" or if using ngPrime styles just [class.hidden]="optionSelected=='Code'"