generic-input.component.ts 10.41 KiB
import { Input, Output, EventEmitter, ChangeDetectorRef } from "@angular/core";
import { BaseComponent } from "../base/base.component";
/*
exemple de template :
<div class="md-form form-sm">
    <input mdbActive type="text" id="form1" class="form-control" [disabled]="isDisabled" [ngModel]="uiValue" (ngModelChange)="setUIValue($event)">
    <label for="form1">{{_title}}</label>
    <small class="text-danger">{{_message}}</small>
</div>
/**
 * classe de gestion générique d'un champ de saisie avec titre, validation et message d'erreur
 * définitions :
 * - modèle : entité mémoire gérée, indépendamment de la façon dont elle est affichée.
 *   A noter que si cette entité est une classe, on peut ne présenter à l'interface qu'un membre de cette classe,
 *   cad que get model() et getModelValue() ne renverront pas la même chose.
 *   Par ex : get model()-> instance_de_la_classe_Toto, getModelValue() -> Toto.unMembreNumerique
 * - valeur gérée : entité elle même si c'est un type simple (number, string, ...) ou une partie d'un classe
 * - UI : interface utilisateur, présentation de la valeur gérée
export abstract class GenericInputComponent extends BaseComponent {
    /**
     * entité mémoire gérée
    protected _model: any;
    /**
     * flag de désactivation de l'input
    @Input('inputDisabled')
    private _inputDisabled: boolean = false;
    /**
     * flag d'affichage du message d'erreur
    public showError = true;
    /**
     * chaîne affichée dans l'input quand aucune valeur n'est saisie
    @Input('title')
    private _title: string;
    /**
     * événement signalant un changement : valeur du modèle, validité, ...
    @Output()
    protected onChange = new EventEmitter<any>();
    /**
     * valeur saisie.
     * Cette variable n'est modifiée que lorsqu'on affecte le modèle ou que l'utilisateur fait une saisie
    private _uiValue: string;
    /**
     * flag de validité de la saisie dans l'UI
     * par ex : est ce bien une valeur numérique ? n'y a-t-il que des minuscules ? etc...
    private _isValidUI = false;
    /**
     * flag de validité de la valeur du modèle
     * par ex : la valeur saisie fait elle bien partie d'un domaine de définition donné ? date inférieure à une limite ? etc...
    private _isValidModel = false;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
/** * message d'erreur UI */ private _errorMessageUI: string; /** * message d'erreur modèle */ private _errorMessageModel: string; constructor(private cdRef: ChangeDetectorRef) { super(); } private get isDisabled(): boolean { return this._inputDisabled; } /** * événement de changement de la validité de la saisie */ private emitValidChanged() { this.onChange.emit({ "action": "valid", "value": this.isValid }); } /** * détection des changements dans l'UI par le ChangeDetector du framework */ protected detectChanges() { if (this.cdRef != undefined) this.cdRef.detectChanges(); } /** * calcul de la validité globale du composant (UI+modèle) */ public get isValid() { return this._isValidUI && this._isValidModel; } private setUIValid(b: boolean) { const old = this.isValid; this._isValidUI = b; if (this.isValid != old) this.emitValidChanged(); } private validateUI() { let { isValid, message } = this.validateUIValue(this._uiValue); this._errorMessageUI = message; this.detectChanges(); this.setUIValid(isValid); return isValid; } private setModelValid(b: boolean) { const old = this.isValid; this._isValidModel = b; if (this.isValid != old) this.emitValidChanged(); } private validateModel() { let { isValid, message } = this.validateModelValue(this.getModelValue()); this._errorMessageModel = message; this.detectChanges(); this.setModelValid(isValid); }