All files / lib/dynamic-form dynamic-form.component.ts

100% Statements 41/41
100% Branches 9/9
100% Functions 25/25
100% Lines 39/39

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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116                                          1x                   17x 17x     17x 17x 17x     5x   81x 80x   92x   88x 88x 88x   2x 1x 45x     2x       17x       22x       5x 5x 5x 4x 4x         17x 17x 17x       2x       1x       1x       1x       1x       21x 21x 21x 21x       4x 4x 4x      
/* eslint-disable @angular-eslint/no-conflicting-lifecycle */
import {
  Component, DoCheck, EventEmitter, Inject, Input, OnChanges, OnDestroy, OnInit, Optional, Output, SimpleChanges,
} from '@angular/core';
import { Subscription } from 'rxjs';
import { DynamicFormAction } from '../dynamic-form-action/dynamic-form-action';
import { DynamicFormElement } from '../dynamic-form-element/dynamic-form-element';
import { FormGroupBase } from '../dynamic-form-field/dynamic-form-field-control';
import { DynamicFormValidationErrors } from '../dynamic-form-validation/dynamic-form-validation-errors';
import { DynamicFormValidationService } from '../dynamic-form-validation/dynamic-form-validation.service';
import { DynamicForm } from './dynamic-form';
import { DynamicFormDefinition } from './dynamic-form-definition';
import { DynamicFormSubmit } from './dynamic-form-submit';
import { DynamicFormTemplate } from './dynamic-form-template';
import { DYNAMIC_FORM_THEME } from './dynamic-form-theme';
import { DynamicFormBuilder } from './dynamic-form.builder';
 
@Component({
  selector: 'dynamic-form',
  templateUrl: './dynamic-form.component.html',
})
export class DynamicFormComponent<
  Value extends { [key: string]: any } = any, Model extends Value = Value
> implements OnInit, OnChanges, OnDestroy, DoCheck {
 
  private _form: DynamicForm<Value, Model>;
  private _formSubmit: Subscription;
  private _formValueChanges: Subscription;
 
  @Input() definition: DynamicFormDefinition;
  @Input() model: Model;
  @Output() valueChange = new EventEmitter<Value>();
  @Output() formSubmit = new EventEmitter<DynamicFormSubmit>();
 
  constructor(
    protected formBuilder: DynamicFormBuilder,
    protected validationService: DynamicFormValidationService,
    @Optional() @Inject(DYNAMIC_FORM_THEME) public theme: string,
  ) {}
 
  get value(): any { return this._form.value; }
 
  get form(): DynamicForm<Value, Model> { return this._form; }
  get formGroup(): FormGroupBase<Value> { return this._form.control; }
 
  get template(): DynamicFormTemplate { return this._form.template; }
 
  get children(): DynamicFormElement[] { return this._form.children; }
  get headerActions(): DynamicFormAction[] { return this._form.headerActions; }
  get footerActions(): DynamicFormAction[] { return this._form.footerActions; }
 
  get errors(): DynamicFormValidationErrors { return this.form.errors; }
  get hasErrors(): boolean { return this.form.hasErrors; }
  get showErrors(): boolean { return this.form.showErrors; }
 
  get errorMessage(): string {
    return this.validationService.getErrorMessage(this.errors);
  }
 
  ngOnInit(): void {
    this.initForm();
  }
 
  ngDoCheck(): void {
    this._form.check();
  }
 
  ngOnChanges({ model, definition }: SimpleChanges): void {
    const modelChanged = model && !model.firstChange;
    const definitionChanged = definition && !definition.firstChange;
    if (modelChanged || definitionChanged) {
      this.destroyForm();
      this.initForm();
    }
  }
 
  ngOnDestroy(): void {
    this._form.destroy();
    this._formSubmit.unsubscribe();
    this._formValueChanges.unsubscribe();
  }
 
  submit(): void {
    this.formSubmit.emit({ value: this.value, model: this.model, files: this.form.getFiles() });
  }
 
  validate(): void {
    this._form.validate();
  }
 
  reset(): void {
    this._form.reset();
  }
 
  resetEmpty(): void {
    this._form.resetEmpty();
  }
 
  resetDefault(): void {
    this._form.resetDefault();
  }
 
  private initForm(): void {
    this.model = this.model || {} as Model;
    this._form = this.formBuilder.initForm<Value, Model>(this.definition, this.model);
    this._formSubmit = this._form.submit$.subscribe({ next: () => this.submit() });
    this._formValueChanges = this.formGroup.valueChanges.subscribe((value) => this.valueChange.emit(value));
  }
 
  private destroyForm(): void {
    this._form.destroy();
    this._formSubmit.unsubscribe();
    this._formValueChanges.unsubscribe();
  }
}