File
Description
Ce composant permet de créer dynamiquement des formulaire à partir
de paramètres passés sous forme d'un tableau d'objets.
Metadata
selector |
pnx-dynamic-form-generator |
styleUrls |
dynamic-form-generator.component.scss |
templateUrl |
dynamic-form-generator.component.html |
autoGenerated
|
Est-ce que
- (autoGenerated == true) : tous les champs du formulaire sont présents
- (autoGenerated == false) : ou bien le formulaire doit être controlé par un champ select
pour afficher/masquer les champs du formulaire. Par défault (autoGenerated == false) le formulaire est controlé par un champ select.
Default value: false
|
defaults
|
Dictionnaire qui permet
- de donner des valeurs par défaut au formulaire
- et d'afficher les champs concernés
(dans le cas où l'input autoGenerated est égal à false) Exemple: defaults = { id_nomenclature_observation_status: [84], id_nomenclature_valid_status = [458,315,320,316,319,317] }
Type: any
|
formsDefinition
|
Type: any[]
|
Methods
initDynamicForm
|
initDynamicForm()
|
Returns: void
|
hasValueChanged
|
hasValueChanged(newValue: any)
|
on teste s'il y a un changement entre this.myFormGroup.value et valueSaved;
Returns: void
|
setForms
|
setForms()
|
Returns: void
|
onFormsChange
|
onFormsChange(newValue: any)
|
Returns: void
|
removeFormControl
|
removeFormControl(i: any)
|
Returns: void
|
addFormControl
|
addFormControl(formDef: any)
|
Returns: void
|
Public formControlBuilded
|
formControlBuilded: boolean
|
Default value: false
|
Public formsDisplayed
|
formsDisplayed: any[]
|
Public formsHidden
|
formsHidden: any[]
|
Public formsSelected
|
formsSelected: any[]
|
Public oldValue
|
oldValue: {}
|
Public selectControl
|
selectControl: any
|
Public update
|
update: any
|
import { Component, OnInit, OnChanges, Input, Output, EventEmitter } from '@angular/core';
import { UntypedFormGroup, UntypedFormControl } from '@angular/forms';
import { DynamicFormService } from './dynamic-form.service';
import * as equal from 'fast-deep-equal/es6';
import { filter } from 'rxjs/operators';
/**
* Ce composant permet de créer dynamiquement des formulaire à partir
* de paramètres passés sous forme d'un tableau d'objets.
*/
@Component({
selector: 'pnx-dynamic-form-generator',
templateUrl: './dynamic-form-generator.component.html',
styleUrls: ['./dynamic-form-generator.component.scss'],
})
export class GenericFormGeneratorComponent implements OnInit, OnChanges {
public formControlBuilded = false;
public selectControl = new UntypedFormControl();
public formsHidden = [];
public formsDisplayed = [];
public oldValue = {};
public update;
@Input() myFormGroup: UntypedFormGroup;
@Output() myFormGroupChange = new EventEmitter<any>();
@Input() formsDefinition: Array<any>;
@Input() selectLabel: string;
@Output() change = new EventEmitter<any>();
/**
* Est-ce que
* - (autoGenerated == true) : tous les champs du formulaire sont présents
* - (autoGenerated == false) : ou bien le formulaire doit être controlé par un champ select
* pour afficher/masquer les champs du formulaire.
* Par défault (autoGenerated == false) le formulaire est controlé par un champ select.
*/
@Input() autoGenerated = false;
/**
* Dictionnaire qui permet
* - de donner des valeurs par défaut au formulaire
* - et d'afficher les champs concernés
* (dans le cas où l'input autoGenerated est égal à false)
* Exemple:
* defaults = {
* id_nomenclature_observation_status: [84],
* id_nomenclature_valid_status = [458,315,320,316,319,317]
* }
*/
@Input() defaults: any;
public formsSelected = [];
constructor(private _dynformService: DynamicFormService) {}
ngOnInit() {
this.formsDefinition = this.formsDefinition || [];
this.initDynamicForm();
this.myFormGroup.valueChanges.subscribe((values) => {
this.onFormsChange(values);
});
}
ngOnChanges(changes) {
// on formdef changes, regenerate the form and UI
// Do not load the form at first change: done by ngOnInit which wait for the component to be ready
if (
changes.formsDefinition &&
!changes.formsDefinition.firstChange &&
changes.formsDefinition.currentValue
) {
for (const controlName in this.myFormGroup.controls) {
this.myFormGroup.removeControl(controlName);
}
this.initDynamicForm();
}
}
initDynamicForm() {
if (this.autoGenerated) {
if (!this.myFormGroup) {
this.myFormGroup = this._dynformService.initFormGroup();
}
// HACK: formeSelect = formDefinition en mode autoGenerated = true
// (on affiche tous les champs sans les filtrer au préalable)
this.formsSelected = this.formsDefinition;
this.formsDefinition.forEach((formDef) => {
if (formDef.type_widget) {
this._dynformService.addNewControl(formDef, this.myFormGroup);
}
// attribution de la valeur par defaut
if (this.defaults && this.defaults[formDef.atribute_name] != null) {
const value = {};
value[formDef.atribute_name] = this.defaults[formDef.atribute_name];
this.myFormGroup.patchValue(value);
}
});
} else {
// dans le cas non auto-généré
// s'il y a des valeurs par defaut
// -on affiche les champs concernés
// - et on donne la valeur par défaut
for (const [defaultKey, defaultValue] of Object.entries(this.defaults || {})) {
const formDef = this.formsDefinition.find((formDef) => formDef.attribut_name == defaultKey);
if (!formDef) {
continue;
}
this.addFormControl(formDef);
const value = {};
value[defaultKey] = defaultValue;
this.myFormGroup.patchValue(value);
}
this.selectControl.valueChanges
.pipe(filter((value) => value !== null))
.subscribe((formDef) => {
this.addFormControl(formDef);
});
this.formsDefinition.sort((a, b) => {
return a.attribut_label.localeCompare(b.attribut_label);
});
}
this.setForms();
this.formControlBuilded = true;
this.myFormGroupChange.emit(this.myFormGroup);
}
/**
* on teste s'il y a un changement entre this.myFormGroup.value et valueSaved;
*/
hasValueChanged(newValue) {
return !equal(newValue, this.oldValue);
}
setForms() {
this.formsDisplayed = this.formsSelected.filter(
(formDef) => !this._dynformService.getFormDefValue(formDef, 'hidden', this.myFormGroup.value)
);
this.formsHidden = this.formsSelected.filter((formDef) =>
this._dynformService.getFormDefValue(formDef, 'hidden', this.myFormGroup.value)
);
}
onFormsChange(newValue) {
if (this.hasValueChanged(newValue)) {
// mise à jour des formulaires affichés / cachés
this.setForms();
// pour dire aux formulaires qu'il y a un changement;
// fy ExpressionChangedAfterItHasBeenCheckedError
setTimeout(() => {
this.update = true;
});
setTimeout(() => {
this.update = false;
}, 500);
this.change.emit(newValue);
this.oldValue = { ...newValue };
}
}
removeFormControl(i) {
const formDef = this.formsSelected[i];
this.formsSelected.splice(i, 1);
this.formsDefinition.push(formDef);
this.myFormGroup.removeControl(formDef.attribut_name);
this.selectControl.setValue(null);
}
addFormControl(formDef) {
this.formsSelected.push(formDef);
this.formsDefinition = this.formsDefinition.filter((form) => {
return form.attribut_name !== formDef.attribut_name;
});
this._dynformService.addNewControl(formDef, this.myFormGroup);
// pour être sûr que les composants (displayed et hidden) soient bien mis à jour)
this.setForms();
}
}