Skip to content

Instantly share code, notes, and snippets.

@JeanPaulll
Created March 24, 2022 23:37
Show Gist options
  • Save JeanPaulll/c5edd4d67654c6d6d206a0e58bae00e1 to your computer and use it in GitHub Desktop.
Save JeanPaulll/c5edd4d67654c6d6d206a0e58bae00e1 to your computer and use it in GitHub Desktop.
Criar Forms Arrays Dinâmicamente
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {FormArray, FormBuilder, FormGroup} from '@angular/forms';
import {environment} from '../../../../environments/environment';
import {MessageBox} from '../../models/util/message-box';
import {UtilForm} from '../../models/util/util-form';
import {FormatForm} from './format-form';
const noop = () => {
};
declare var toastr: any;
/**
* @author Jean Paul - <jeanpaulwebb@gmail.com>
* @class FormArrayBaseComponent
* @description Criar Forms Arrays Dinâmicamente
* @date 16/06/2021
*/
@Component({
selector: 'form-array-base',
template: ' '
})
export class FormArrayBaseComponent implements OnInit {
@Output('form') form$: EventEmitter<FormArray> = new EventEmitter<FormArray>();
@Output('events') events$: EventEmitter<FormArrayEvent> = new EventEmitter<FormArrayEvent>();
public onFill: EventEmitter<any> = new EventEmitter();
public dev = (environment.ENV == 'dev');
public utilForm = UtilForm;
public formReady = false;
@Input() title = '';
public loadForm = false;
protected onAdd: Function = noop;
protected afterAdd: Function = noop;
protected onRemove: Function = noop;
protected afterRemove: Function = noop;
protected onEdit: Function = noop;
protected afterEdit: Function = noop;
protected indexEdit: number;
private __messageBox = new MessageBox();
private _ready = {form: false, formInner: false, data: false};
private preserveInstance = false;
constructor(formatForm?: FormatForm<any>) {
if (formatForm) {
this.formatForm = formatForm;
} else {
this.formInner = this.getForm();
}
}
private _formatForm: FormatForm<any>;
get formatForm(): FormatForm<any> {
return this._formatForm;
}
set formatForm(value: FormatForm<any>) {
this._formatForm = value;
this.formInner = this.getForm();
}
_showForm = false;
get showForm() {
return this._showForm;
}
set showForm(show: boolean) {
this._showForm = show;
if (show) {
setTimeout(() => this.loadForm = true);
} else {
this.resetForm();
this.loadForm = false;
if (this.visualizeRoot != undefined) {
this.visualize = this.visualizeRoot;
}
}
this.events$.emit({type: 'showForm', data: show});
}
protected _formInner: FormGroup;
get formInner() {
return this._formInner;
}
set formInner(form: FormGroup) {
if (!(form instanceof FormGroup)) {
return;
}
this._formInner = form;
this.formInnerChanges();
this._ready.formInner = true;
}
protected _form: FormArray = new FormBuilder().array([]);
get form() {
return this._form;
}
@Input('formArray')
set form(form: FormArray) {
if (form instanceof FormArray) {
this._form = form;
this._ready.form = true;
if (!this._ready.data) {
this.data = this.data;
}
}
}
public get value() {
return this.form.value;
}
protected _data: any[] | any = [];
get data() {
return this._data;
}
@Input()
set data(data: any) {
this._data = data || [];
if (!this.form) {
return;
}
this.fill(data);
this._ready.data = true;
}
protected _dataInner: any[] | any = [];
get dataInner() {
return this._dataInner;
}
@Input()
set dataInner(dataInner: any) {
this._dataInner = this.normalizeDataForm(dataInner);
if (!this.formInner) {
return;
}
this.formInner.patchValue(this._dataInner);
}
protected _visualizeRoot: boolean;
get visualizeRoot(): boolean {
return this._visualizeRoot;
}
@Input('visualize')
set visualizeRoot(visualize: boolean) {
this._visualizeRoot = visualize;
this.visualize = visualize;
}
protected _visualize = false;
get visualize() {
return this._visualize;
}
set visualize(visualize: boolean) {
this._visualize = visualize;
// if(this.visualizeRoot != undefined) {
//
// }
this.checkVisualize();
// if (!this.formInner) return;
// if (visualize === true) {
// UtilForm.disableAll(this.form);
// UtilForm.disableAll(this.formInner);
// } else {
// this.form.enable();
// this.formInner.enable();
// }
}
protected _bloqueado = false;
get bloqueado() {
return this._bloqueado;
}
@Input()
set bloqueado(bloqueado: boolean) {
this._bloqueado = bloqueado;
}
private _itemEdit: any;
get itemEdit(): any {
return this._itemEdit;
}
set itemEdit(item: any) {
this._itemEdit = item;
if (!item) {
this.indexEdit = undefined;
}
}
static clearFormArray(formArray: FormArray, repeat = true) {
if (!formArray) {
return;
}
while (formArray.controls.length) {
formArray.removeAt(0);
}
if (formArray.controls.length && repeat) {
this.clearFormArray(formArray, false);
}
}
public afterFill() {
};
public beforeFill = (data) => data;
_enable() {
return this.visualize ? 'disable' : 'enable';
}
cleanItemEdit() {
this.itemEdit = undefined;
}
setModel(modelDefault: any, noRequireds?: string[]) {
this._formatForm.setModel(modelDefault, noRequireds);
}
setPreserveInstance(preserveInstance: boolean) {
this.preserveInstance = preserveInstance;
}
errorGetForm() {
throw new Error(`✖ método não implementado.
Nos componentes com "extends FormArrayBaseComponent" é necessário
sobrescrever o método "getForm" no seguinte padrão:
class myComponent extends FormArrayBaseComponent {
...
getForm(data: any) {
if(!data) return;
return new FormGroup({
id: new FormControl(data.id)
...
})
};
...
}`);
}
getForm(data?: any) {
const fb = new FormBuilder();
if (!this.formatForm) {
return fb.group(data);
}
const form = this.formatForm.getForm(data);
if (typeof this.formInnerChanges === 'function' && this.formInner) {
try {
this.formInnerChanges(form);
} catch (e) {
console.error(e);
}
}
return form;
};
fill(data?: any) {
if (!data) {
return;
}
data = this.beforeFill(data);
if (this.preserveInstance) {
this.form.patchValue(data);
} else {
FormArrayBaseComponent.clearFormArray(this.form);
if (typeof data != 'object') {
return;
}
if (!this.getForm) {
return;
}
for (let i = 0; i < data.length; i++) {
if (!this.form.controls[i] && data[i]) {
const form = this.getForm(data[i]);
(this.form as FormArray).push(form);
}
}
}
this.checkVisualize();
this.onFill.emit(true);
this.afterFill();
}
setFormatForm(formatForm?: FormatForm<any>) {
if (formatForm) {
this.formatForm = formatForm;
}
}
checkVisualize() {
if (!this.formInner) {
return;
}
if (this.visualize === true) {
UtilForm.disableAll(this.form);
UtilForm.disableAll(this.formInner);
} else {
this.form.enable();
this.formInner.enable();
}
}
verificaLista() {
if (this.formInner) {
const fullKeys = Object.keys(this.formInner.getRawValue());
const keys = Object.keys(this.formInner.value);
const disableds = fullKeys.filter(k => !keys.includes(k));
this.formatForm.setDisableds(disableds);
this.form.controls.map(ctrl => {
disableds.map(f => {
if (ctrl.get(f)) {
ctrl.get(f).disable();
}
});
// const value = (typeof ctrl['getRawValue'] == 'function') ? ctrl['getRawValue']() : ctrl.value;
// this.form.push(this.getForm(value));
});
}
// FormArrayBaseComponent.clearFormArray(this.form);
// this.form.controls.map(ctrl => {
// const value = (typeof ctrl['getRawValue'] == 'function') ? ctrl['getRawValue']() : ctrl.value;
// this.form.push(this.getForm(value));
// })
}
add(data: any = this.formInner.value, editarPorId: boolean = true) {
const pass = this.onAdd();
if (pass === false) {
return;
}
data = this.normalizeDataForm(data || {});
let control;
if (this.itemEdit) {
const itemEdit = this.itemEdit.value;
let index = null;
if (editarPorId) {
index = itemEdit.id ? (this.form.value as any[]).findIndex(v => v.id == itemEdit.id) : this.indexEdit;
} else {
index = this.indexEdit;
}
if (this.form.at(index)) {
this.form.at(index).patchValue(data);
control = this.form.at(index);
} else {
this.__messageBox.notifyError('Erro ao atualizar');
// toastr.error("Erro ao atualizar");
return;
}
this.itemEdit = undefined;
} else {
if (this.formInner.valid || pass === true) {
if (this.getForm) {
const form = this.getForm(data);
(this.form as FormArray).push(form);
this.form.markAsDirty();
control = form;
}
} else {
this.__messageBox.notifyError('Preencha os campos obrigatórios');
// toastr.error("Preencha os campos obrigatórios");
if (this.dev) {
UtilForm.showFormErrors(this.formInner);
}
return;
}
}
this.resetForm();
this.showForm = false;
// this.data = this.form.getRawValue();
this.afterAdd();
this.events$.emit({type: 'add'});
return control;
}
// cancelar() {
// this.formInner.dirty
// ? this.messageBox.alertConfirm('Deseja realmente cancelar?', () => super.cancel())
// : super.cancel();
// }
normalizeDataForm(data: any) {
const dataDefault = this.formInner.getRawValue();
return Object.keys(dataDefault).reduce((va, k) => {
if (dataDefault[k] && typeof dataDefault[k] === 'object' && va[k] == null) {
va[k] = Array.isArray(dataDefault[k]) ? [] : {};
}
return va;
}, Object.assign({}, data));
}
public remove(i: number, confirmed = false): void {
const pass = this.onRemove();
if (!i && i != 0) {
return;
}
if (pass === false) {
return;
}
if (pass === true) {
confirmed = true;
}
const self = this;
if (!confirmed) {
this.__messageBox.alertConfirm('Deseja realmente excluir o registro?', (result) => {
if (result) {
if (result.isConfirmed) {
(self.form as FormArray).removeAt(+i);
self.resetForm();
}
}
});
} else {
(this.form as FormArray).removeAt(+i);
this.resetForm();
}
this.afterRemove();
this.events$.emit({type: 'remove'});
}
public cancel(confirmCallback?: boolean | Function) {
const conf = (callback) => this.__messageBox.alertConfirm(UtilForm.msg.cancel, () => callback());
const cc = () => {
this.itemEdit = undefined;
this.showForm = false;
this.resetForm();
this.events$.emit({type: 'cancel'});
typeof confirmCallback === 'function' ? confirmCallback() : null;
};
confirmCallback ? conf(cc) : cc();
}
public edit(i: number, visualize?: boolean, callback = () => {
}): void {
if (!visualize) {
visualize = false;
}
this.onEdit();
if (!this.form.get('' + i)) {
return;
}
this.itemEdit = this.form.get('' + i);
this.indexEdit = i;
const itemEdit = this.itemEdit.value;
this.resetForm();
this.showForm = true;
setTimeout(() => {
this.dataInner = itemEdit;
if (visualize) {
this.formInner.disable();
this.form.disable();
}
setTimeout(() => {
callback();
});
});
this.afterEdit(itemEdit);
this.events$.emit({type: 'edit'});
}
formInnerChanges(form?: any) {
}
readyForm() {
setTimeout(() => {
this.form$.emit(this.form);
});
}
ready() {
setTimeout(() => this.formReady = true);
}
formErrors() {
UtilForm.showFormErrors(this.formInner);
}
ngOnInit() {
this.form$.emit(this.form);
}
protected resetForm() {
this.formInner.reset();
this.dataInner = this.getForm().value;
if (this._bloqueado) {
this.visualize = false;
this.bloqueado = false;
}
}
}
export class FormArrayEvent {
type = null; // add, edit, remove, delete, cancel, showForm
data? = null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment