Skip to content
Snippets Groups Projects
fieldset-container.component.ts 6.69 KiB
import { Component, Input, Output, EventEmitter, QueryList, ViewChildren, DoCheck, AfterViewInit } from "@angular/core";

import { FieldsetContainer } from "../../formulaire/elements/fieldset-container";
import { FieldSetComponent } from "../field-set/field-set.component";
import { FieldSet } from "../../formulaire/elements/fieldset";
import { FormulaireDefinition } from "../../formulaire/definition/form-definition";
import { I18nService } from "../../services/internationalisation.service";
import { ApplicationSetupService } from "../../services/app-setup.service";

@Component({
    selector: "fieldset-container",
    templateUrl: "./fieldset-container.component.html",
    styleUrls: [
        "./fieldset-container.component.scss"
    ]
})
export class FieldsetContainerComponent implements DoCheck, AfterViewInit {

    public get title(): string {
        if (this._container) {
            return this._container.label;
        }
    }

    public get fieldsets() {
        return this._container.fieldsets;
    }

    public get isValid() {
        return this._isValid;
    }
    @Input()
    private _container: FieldsetContainer;

    /**
     * liste des composants FieldSet enfants
     */
    @ViewChildren(FieldSetComponent)
    private _fieldsetComponents: QueryList<FieldSetComponent>;

    /**
     * flag de validité des FieldSet enfants
     */
    private _isValid = false;

    /**
     * événément de changement d'état d'un radio
     */
    @Output()
    private radio = new EventEmitter<any>();

    /**
     * événément de changement de validité
     */
    @Output()
    private validChange = new EventEmitter();

    /**
     * événément de changement de valeur d'un input
     */
    @Output()
    private inputChange = new EventEmitter();

    /** événement signalant un appui sur TAB ou SHIFT+TAB */
    @Output()
    protected tabPressed = new EventEmitter<any>();

    public constructor(
        private i18nService: I18nService,
        private appSetupService: ApplicationSetupService
    ) {}

    /**
     * Ajoute un nouveau sous-nub (Structure, PabCloisons, YAXN… selon le cas)
     * dans un nouveau fieldset
     */
    private addSubNub(after?: FieldSet, clone: boolean = false) {
        if (after) {
            const newFs = this._container.addFromTemplate(0, after.indexAsKid());
            if (this.appSetupService.enableEmptyFieldsOnFormInit && ! clone) {
                newFs.emptyFields();
            }
            if (clone) {
                // replace in-place to change properties (overkill)
                // @WTF why only those two ?
                newFs.setPropValue("structureType", after.properties.getPropValue("structureType"));
                newFs.setPropValue("loiDebit", after.properties.getPropValue("loiDebit"));
                // copy param values
                for (const p of after.nub.prms) {
                    newFs.nub.getParameter(p.symbol).loadObjectRepresentation(p.objectRepresentation());
                }
            }
        } else {
            const newFs = this._container.addFromTemplate(0);
            if (this.appSetupService.enableEmptyFieldsOnFormInit && ! clone) {
                newFs.emptyFields();
            }
        }
    }

    private onFieldsetListChange() {
    }

    public ngAfterViewInit() {
        this.onFieldsetListChange();
        this._fieldsetComponents.changes.subscribe(_ => this.onFieldsetListChange());
    }

    /*
     * gestion des événements clic sur les radios :
     * réception d'un message du composant enfant (field-set)
     * cf. https://angular.io/guide/component-interaction#parent-listens-for-child-event
     */
    public onRadioClick(info: any) {
        // on renvoie l'info au parent
        this.radio.emit(info);
    }

    public ngDoCheck() {
        this.updateValidity();
    }

    /**
    * calcul de la validité de tous les FieldSet de la vue
    */
    private updateValidity() {
        this._isValid = false;

        if (this._fieldsetComponents !== undefined && this._fieldsetComponents.length > 0) {
            this._isValid = this._fieldsetComponents.reduce(
                // callback
                (
                    // accumulator (valeur précédente du résultat)
                    acc,
                    // currentValue (élément courant dans le tableau)
                    fieldset,
                    // currentIndex (indice courant dans le tableau)
                    currIndex,
                    // array (tableau parcouru)
                    array
                ) => {
                    return acc && fieldset.isValid;
                }
                // valeur initiale
                , this._fieldsetComponents.length > 0);
        } else {
            // empty / hidden container ? everything OK.
            this._isValid = true;
        }

        this.validChange.emit();
    }

    /**
     * réception d'un événement de validité de FieldSet
     */
    public onFieldsetValid() {
        this.updateValidity();
    }

    /**
    * réception d'un événement de changement de valeur d'un input
    */
    public onInputChange($event) {
        this.inputChange.emit($event);
    }

    /**
     * met à jour les paramètres liés
     */
    public updateLinkedParameters() {
        this._fieldsetComponents.forEach(fsc => fsc.updateLinkedParameters());
    }

    /**
    * réception d'un événement de demande d'ajout d'un FieldSet
    */
    public onAddFieldset(evt: { fs: FieldSet, clone: boolean }) {
        this.addSubNub(evt.fs, evt.clone);
    }

    /**
    * réception d'un événement de demande de suppression d'un FieldSet
    */
    public onRemoveFieldset(fs: FieldSet) {
        const form = this._container.parent as FormulaireDefinition;
        form.removeFieldset(fs);
    }

    /**
    * réception d'un événement de demande de remontée d'un FieldSet
    */
    public onMoveFieldsetUp(fs: FieldSet) {
        const form = this._container.parent as FormulaireDefinition;
        form.moveFieldsetUp(fs);
    }

    /**
    * réception d'un événement de demande de descente d'un FieldSet
    */
    public onMoveFieldsetDown(fs: FieldSet) {
        const form = this._container.parent as FormulaireDefinition;
        form.moveFieldsetDown(fs);
    }

    /**
     * Renvoie l'événement au composant du dessus
     */
    public onTabPressed(event) {
        this.tabPressed.emit(event);
    }

    public openHelp() {
        window.open("assets/docs/" + this.appSetupService.language + "/calculators/" + this._container.helpLink, "_blank");
    }

    public get enableHelpButton() {
        return this._container && this._container.helpLink;
    }

    public get uitextOpenHelp() {
        return this.i18nService.localizeText("INFO_CALCULATOR_OPEN_HELP");
    }
}