Add (change) event listener to a field at runtime

565 Views Asked by At

I have some field for a form, that are rendered using a JSON and an *ngFor. The number and order of the fields can vary, as well as the type. They could be either datetime fields or text field, based on parameters that came on the JSON.

The only constant is that the first two are always datetime fields, StartDate and EndDate.

Now I would like to be able to detect when the values of these fields change, so I can do some checking if the StartDate is lower or equal than the EndDate.

Here is my template:

// Code to render the fields, be it datetime or text
  <div class="form-group">
  <div *ngIf="IsDateTime(campo.data_type); else textField">
       <app-datetimepicker #campoData [Cabecalho]="campo.alias" ></app-datetimepicker>
  </div>
    <ng-template #textField>
     <label>{{campo.alias}}</label>
     <input type="text" class="form-control">
    </ng-template> 

Since the fields don't exist at compile time only after the request for the JSON finishes, I cannot add (change) to the HTML, also because there might be other datetime inputs but I only want the first two.

I can get the two fields and their values, I am searching for a way to add a listener for when the input values changes, but so far had no success.

I've tried Renderer2 but got and error message, and most of the questions I find tell me to add the (change) event to the template, but that doesn't fit what I am needing.

How could I go around doing this?

1

There are 1 best solutions below

0
Juan Vicente Berzosa Tejero On

You can try to do something like this:

  1. Declare this new observable:
formValueChanges$: Observable<any>;
  1. once you have your form initialized, subscribe to its changes:
// yourForm should be the name of your form
this.formValueChanges$ = this.yourForm.valueChanges
   .pipe(
      //takeUntil(this.destroy$),
      debounceTime(0),
      distinctUntilChanged(),
      shareReplay(1)
    );
  1. Once you have that subscribtion, you can filter by the field you wanted (campo in your example, I guess):
this.formValueChanges$  
   .pipe(   
      //takeUntil(this.destroy$),
        distinctUntilKeyChanged('campo')
      )
      .subscribe(formValue => {

         // Here should be your logic
      });

NOTE: You have to do the appropriate imports

import {
  map,
  takeUntil,
  filter,
  debounceTime,
  distinctUntilChanged,
  shareReplay,
  distinctUntilKeyChanged,
  finalize,
} from 'rxjs/operators';
import { Observable } from 'rxjs';