All files / src/app/core/services form-error.service.ts

57.14% Statements 24/42
25% Branches 4/16
66.66% Functions 6/9
84% Lines 21/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 5911x 11x               11x   3x   3x           3x 4x 4x 4x 4x   4x 4x 4x   4x     4x 2x 2x                     4x             1x 1x   1x      
import { Injectable } from '@angular/core';
import { TranslatorService } from './translator.service';
import { AbstractControl, FormGroup, ValidationErrors } from '@angular/forms';
import { Subscription } from 'rxjs';
import { BackendError } from '@core/errors/backend-error';
 
@Injectable({
  providedIn: 'root'
})
export class FormErrorService  {
    // useful to cancel subsriptions when user changes a value
    private cleanupSubscriptions = new Map<AbstractControl, Subscription>();
 
  constructor(private translatorService: TranslatorService) { }
 
  setBackendErrors(
    form: FormGroup,
    errorMap: Record<string, BackendError[]> 
  ): void {
    for (const [fieldName, errors] of Object.entries(errorMap)) {
      const control = form.get(fieldName);
      if (control) {
        const translatedErrors = errors.map((err:BackendError) =>
          this.translatorService.translateError(err.code, err.details)
        );
        const controlErrors = control.errors ?? {} as ValidationErrors;
        controlErrors['backend'] = translatedErrors;
        control.setErrors(controlErrors);
        // unsub the previous subscription if it exists
        this.cleanupSubscriptions.get(control)?.unsubscribe();
 
        // automatic cleanup errors are removed if user changes form control value
        const sub = control.valueChanges.subscribe(() => {
          const currentErrors = control.errors;
          Iif (currentErrors && currentErrors['backend']) {
            delete currentErrors['backend'];
            // replace with cleaned up errors
            if (Object.keys(currentErrors).length > 0) {
              control.setErrors(currentErrors);
            } else {
              control.setErrors(null);
            }
          }
        });
 
        this.cleanupSubscriptions.set(control, sub);
      }
    }
  }
  
  // removes all subscriptions, useful to avoid memory leaks on form components destroy
  cleanup(): void {
    for (const sub of this.cleanupSubscriptions.values()) {
      sub.unsubscribe();
    }
    this.cleanupSubscriptions.clear();
  }
}