UNPKG

grcm-components

Version:

> ⚡ Crea formularios dinámicos en Angular de forma rápida, limpia y reutilizable.

574 lines (561 loc) 40.5 kB
import { RouterLink } from '@angular/router'; import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i0 from '@angular/core'; import { input, output, computed, Component, inject, Injector, DestroyRef, viewChild, ViewContainerRef, OutputEmitterRef, isSignal, forwardRef, viewChildren, signal, ChangeDetectionStrategy } from '@angular/core'; import { distinctUntilChanged, Subject, debounceTime } from 'rxjs'; import * as i2 from '@angular/forms'; import { ReactiveFormsModule, NG_VALUE_ACCESSOR, FormBuilder, Validators, FormsModule } from '@angular/forms'; import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop'; class GrcmButtonComponent { label = input(''); title = input(''); disabled = input(false); link = input(null); type = input('button'); variant = input('primary'); outline = input(false); size = input('default'); additionalClasses = input(''); icon = input(''); submitter = input(null); fontSizeIcon = input(6); clicked = output(); classes = computed(() => { return `w-100 btn btn-${(this.outline() ? 'outline-' : '') + this.variant() + (this.size() ? ` btn-${this.size()} ` : ' ') + this.additionalClasses()}`; }); click() { this.clicked.emit(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.6", type: GrcmButtonComponent, isStandalone: true, selector: "lib-grcm-button", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, link: { classPropertyName: "link", publicName: "link", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, outline: { classPropertyName: "outline", publicName: "outline", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, additionalClasses: { classPropertyName: "additionalClasses", publicName: "additionalClasses", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, submitter: { classPropertyName: "submitter", publicName: "submitter", isSignal: true, isRequired: false, transformFunction: null }, fontSizeIcon: { classPropertyName: "fontSizeIcon", publicName: "fontSizeIcon", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: "<button [type]=\"type()\" [attr.disabled]=\"disabled() ? 'disabled' : null\" (click)=\"click()\" [title]=\"title()\" [ngClass]=\"classes()\" [routerLink]=\"link()\" [attr.data-submitter]=\"submitter() ? submitter() : null\">\r\n @if (icon()) {\r\n <i [ngClass]=\"'fs-' + fontSizeIcon() + ' bi bi-' + icon()\"></i>\r\n }\r\n {{ label() }}\r\n</button>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmButtonComponent, decorators: [{ type: Component, args: [{ selector: 'lib-grcm-button', imports: [CommonModule, RouterLink], template: "<button [type]=\"type()\" [attr.disabled]=\"disabled() ? 'disabled' : null\" (click)=\"click()\" [title]=\"title()\" [ngClass]=\"classes()\" [routerLink]=\"link()\" [attr.data-submitter]=\"submitter() ? submitter() : null\">\r\n @if (icon()) {\r\n <i [ngClass]=\"'fs-' + fontSizeIcon() + ' bi bi-' + icon()\"></i>\r\n }\r\n {{ label() }}\r\n</button>\r\n" }] }] }); /* eslint-disable @typescript-eslint/no-explicit-any */ function createGrcmControl(data) { return data; } /* eslint-disable @typescript-eslint/no-explicit-any */ class GrcmControlComponent { _injector = inject(Injector); _destroyRef = inject(DestroyRef); _container = viewChild('container', { read: ViewContainerRef }); _grcmFormComponent = inject(GrcmFormComponent); formControlName = input.required(); _componentRef; _componentRefFormField; id = computed(() => this._grcmFormComponent.identifier() + '_' + this.formControlName()); _form = computed(() => this._grcmFormComponent.form()); _data = computed(() => this._grcmFormComponent.data().controls[this.formControlName()]); control = computed(() => this._form()?.controls[this.formControlName()]); _hasPendingValue = false; _hasPendingDisabledValue = false; _pendingValue = null; _onChange = null; _onTouched = null; _pendingDisabled = null; ngAfterContentInit() { this.initialize(); } initialize() { this.createComponents(); this.setInputsOutputs(); this.setClasses(); this.flushPendingControlValueAccessors(); } createComponents() { const { component, formFieldComponent } = this._data(); const viewContainer = this._container(); if (!formFieldComponent || !viewContainer) return; viewContainer.clear(); this._componentRefFormField = viewContainer.createComponent(formFieldComponent); this._componentRefFormField.setInput('control', this.control()); this._componentRefFormField.setInput('id', this.id()); const formFieldInstance = this._componentRefFormField.instance; formFieldInstance.controlView().clear(); this._componentRef = formFieldInstance.controlView().createComponent(component); } setInputsOutputs() { const args = this._data().args; if (!args) return; const { control = {}, formField = {} } = args; const componentRef = this._componentRef; const componentRefFormField = this._componentRefFormField; const setInputsOutputs = (args, componentRef) => { const keys = Object.keys(args); keys.forEach((argProperty) => { const argValue = args[argProperty]; const componentProperty = componentRef.instance[argProperty]; switch (typeof componentProperty) { case 'function': if (isSignal(argValue)) { const obs = toObservable(argValue, { injector: this._injector }).subscribe(() => componentRef.setInput(argProperty, argValue())); this._destroyRef.onDestroy(() => obs.unsubscribe()); } else { componentRef.setInput(argProperty, argValue); } break; case 'object': if (!(componentProperty instanceof OutputEmitterRef)) return; const subs = componentProperty.subscribe(argValue); this._destroyRef.onDestroy(() => subs.unsubscribe()); } }); }; setInputsOutputs(control, componentRef); setInputsOutputs(formField, componentRefFormField); } setClasses() { const classes = this._data().classes; if (!classes) return; const { control, formField } = classes; if (control) this._componentRef.location.nativeElement.classList = control; if (formField) this._componentRefFormField.location.nativeElement.classList = formField; } flushPendingControlValueAccessors() { const instance = this._componentRef?.instance; if (this._hasPendingValue) { instance.writeValue(this._pendingValue); this._hasPendingValue = false; } if (this._onChange) { instance.registerOnChange(this._onChange); this._onChange = null; } if (this._onTouched) { instance.registerOnTouched(this._onTouched); this._onTouched = null; } if (this._hasPendingDisabledValue) { instance.setDisabledState?.(this._pendingDisabled); this._hasPendingDisabledValue = false; } } writeValue(obj) { const instance = this._componentRef?.instance; if (instance) { instance.writeValue(obj); return; } this._hasPendingValue = true; this._pendingValue = obj; } registerOnChange(fn) { const instance = this._componentRef?.instance; if (instance) { instance.registerOnChange(fn); return; } this._onChange = fn; } registerOnTouched(fn) { const instance = this._componentRef?.instance; if (instance) { instance.registerOnTouched(fn); return; } this._onTouched = fn; } setDisabledState(isDisabled) { const instance = this._componentRef?.instance; if (instance) { instance?.setDisabledState?.(isDisabled); return; } this._hasPendingDisabledValue = true; this._pendingDisabled = isDisabled; } ngOnDestroy() { this._componentRef?.destroy(); this._componentRefFormField?.destroy(); this._container()?.clear(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.6", type: GrcmControlComponent, isStandalone: true, selector: "lib-grcm-control", inputs: { formControlName: { classPropertyName: "formControlName", publicName: "formControlName", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "attr.data-control-id": "id()" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => GrcmControlComponent), multi: true } ], viewQueries: [{ propertyName: "_container", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "<ng-container #container></ng-container>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmControlComponent, decorators: [{ type: Component, args: [{ selector: 'lib-grcm-control', imports: [CommonModule, ReactiveFormsModule], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => GrcmControlComponent), multi: true } ], host: { '[attr.data-control-id]': 'id()' }, template: "<ng-container #container></ng-container>\r\n" }] }] }); /* eslint-disable @typescript-eslint/no-explicit-any */ class GrcmFormComponent { grcmControls = viewChildren(GrcmControlComponent, { read: ViewContainerRef }); _destroyRef = inject(DestroyRef); _formBuilder = inject(FormBuilder); data = input.required(); additionalClasses = computed(() => this.data().form.classes || ""); buildForm = output(); formSubmit = output(); formChange = output(); _form = signal(null); form = this._form.asReadonly(); formKeys = []; templates = input({}); identifier = computed(() => this.data().form.id); formControlNames = computed(() => Object.keys(this._form()?.controls || {})); ngOnInit() { this.initialize(); } ngAfterViewInit() { this.buildForm.emit(this.form()); } initialize() { this.initForm(); this.initSubscriptionsForControlValueChanges(); } initForm() { const data = this.data(); this._form.set(this._formBuilder.record({}, { validators: data.form.validators, asyncValidators: data.form.asyncValidators, updateOn: data.form.updateOn || 'change' })); Object.keys(data.controls).forEach((name) => { const dataControl = data.controls[name]; this.addControl(name, dataControl); }); } addControl(name, control) { this._form()?.addControl(name, this._formBuilder.control(control.value, [...control.validators || []], [...control.asyncValidators || []])); } initSubscriptionsForControlValueChanges() { const form = this.form(); if (!form) return; this.formControlNames().forEach((key) => { if (!this.data().controls[key].valueChangesSubscribe) return; form.controls[key].valueChanges.pipe(distinctUntilChanged(), takeUntilDestroyed(this._destroyRef)).subscribe((value) => { this.formChange.emit({ field: key, newValue: value }); }); }); } getErrors(errors) { if (!errors) return []; return Object.keys(errors); } onSubmit(event = null) { const submitter = event?.submitter?.dataset['submitter'] || null; const form = this.form(); this.markAsTouched(); if (!form || form.invalid) return; if (form.valid) this.formSubmit.emit({ form, submitter }); } markAsTouched() { const form = this.form(); form?.markAsTouched(); form?.updateValueAndValidity(); } getDataForTemplateContext(formControlName = null) { const form = this.form(); if (!form) return {}; const data = { form }; if (formControlName) { data['control'] = form.controls[formControlName]; } return data; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.6", type: GrcmFormComponent, isStandalone: true, selector: "lib-grcm-form", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, templates: { classPropertyName: "templates", publicName: "templates", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { buildForm: "buildForm", formSubmit: "formSubmit", formChange: "formChange" }, viewQueries: [{ propertyName: "grcmControls", predicate: GrcmControlComponent, descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "\r\n\r\n<ng-template #renderTemplate let-templateKey let-controlName>\r\n @let tmpl = templates()[templateKey];\r\n @if (tmpl) {\r\n <ng-container *ngTemplateOutlet=\"tmpl; context: getDataForTemplateContext(controlName)\"></ng-container>\r\n }\r\n</ng-template>\r\n\r\n<!-- <ng-container *ngTemplateOutlet=\"renderTemplate; context: {\r\n templateKey: 'before_' + controlName,\r\n controlName: controlName\r\n}\"></ng-container> -->\r\n\r\n@let formInstance = form();\r\n@if (formInstance) {\r\n <form [formGroup]=\"formInstance\" (ngSubmit)=\"onSubmit($event)\" [ngClass]=\"additionalClasses()\" novalidate>\r\n @let beforeFormTemplate = templates()[\"beforeFormTemplate\"];\r\n @if (beforeFormTemplate) {\r\n <ng-container *ngTemplateOutlet=\"beforeFormTemplate; context: getDataForTemplateContext()\"></ng-container>\r\n }\r\n @for (controlName of formControlNames(); track controlName) {\r\n @let beforeControlTemplate = templates()[\"before_\" + controlName];\r\n @if (beforeControlTemplate) {\r\n <ng-container *ngTemplateOutlet=\"beforeControlTemplate; context: getDataForTemplateContext(controlName)\"></ng-container>\r\n }\r\n <lib-grcm-control [formControlName]=\"controlName\" style=\"width: 100%;\"></lib-grcm-control>\r\n @let afterControlTemplate = templates()[\"after_\" + controlName];\r\n @if (afterControlTemplate) {\r\n <ng-container *ngTemplateOutlet=\"afterControlTemplate; context: getDataForTemplateContext(controlName)\"></ng-container>\r\n }\r\n }\r\n @let afterFormTemplate = templates()[\"afterFormTemplate\"];\r\n @if (afterFormTemplate) {\r\n <ng-container *ngTemplateOutlet=\"afterFormTemplate; context: getDataForTemplateContext()\"></ng-container>\r\n }\r\n </form>\r\n}\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: GrcmControlComponent, selector: "lib-grcm-control", inputs: ["formControlName"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmFormComponent, decorators: [{ type: Component, args: [{ selector: 'lib-grcm-form', imports: [CommonModule, ReactiveFormsModule, GrcmControlComponent], template: "\r\n\r\n<ng-template #renderTemplate let-templateKey let-controlName>\r\n @let tmpl = templates()[templateKey];\r\n @if (tmpl) {\r\n <ng-container *ngTemplateOutlet=\"tmpl; context: getDataForTemplateContext(controlName)\"></ng-container>\r\n }\r\n</ng-template>\r\n\r\n<!-- <ng-container *ngTemplateOutlet=\"renderTemplate; context: {\r\n templateKey: 'before_' + controlName,\r\n controlName: controlName\r\n}\"></ng-container> -->\r\n\r\n@let formInstance = form();\r\n@if (formInstance) {\r\n <form [formGroup]=\"formInstance\" (ngSubmit)=\"onSubmit($event)\" [ngClass]=\"additionalClasses()\" novalidate>\r\n @let beforeFormTemplate = templates()[\"beforeFormTemplate\"];\r\n @if (beforeFormTemplate) {\r\n <ng-container *ngTemplateOutlet=\"beforeFormTemplate; context: getDataForTemplateContext()\"></ng-container>\r\n }\r\n @for (controlName of formControlNames(); track controlName) {\r\n @let beforeControlTemplate = templates()[\"before_\" + controlName];\r\n @if (beforeControlTemplate) {\r\n <ng-container *ngTemplateOutlet=\"beforeControlTemplate; context: getDataForTemplateContext(controlName)\"></ng-container>\r\n }\r\n <lib-grcm-control [formControlName]=\"controlName\" style=\"width: 100%;\"></lib-grcm-control>\r\n @let afterControlTemplate = templates()[\"after_\" + controlName];\r\n @if (afterControlTemplate) {\r\n <ng-container *ngTemplateOutlet=\"afterControlTemplate; context: getDataForTemplateContext(controlName)\"></ng-container>\r\n }\r\n }\r\n @let afterFormTemplate = templates()[\"afterFormTemplate\"];\r\n @if (afterFormTemplate) {\r\n <ng-container *ngTemplateOutlet=\"afterFormTemplate; context: getDataForTemplateContext()\"></ng-container>\r\n }\r\n </form>\r\n}\r\n" }] }] }); /* eslint-disable @typescript-eslint/no-explicit-any */ class GrcmFormFieldComponent { _destroyRef = inject(DestroyRef); controlView = viewChild.required('controlView', { read: ViewContainerRef }); control = input.required(); id = input.required(); _formComponent = inject(GrcmFormComponent); label = input(""); _isRequired = signal(false); isRequired = this._isRequired.asReadonly(); _useCompleteLabel = signal(false); useCompleteLabel = this._useCompleteLabel.asReadonly(); requiredTag = "*"; optionalTag = "(Opcional)"; form = computed(() => this._formComponent.form()); completeLabel = computed(() => { return this.label() + (this.useCompleteLabel() ? (this.isRequired() ? this.requiredTag : this.optionalTag) : ""); }); ngOnInit() { this.initialize(); } initialize() { this.setIsRequired(); this.initControlStatusChanges(); this.initFormStatusChanges(); } initControlStatusChanges() { this.control().statusChanges.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => { this.setIsRequired(); }); } initFormStatusChanges() { const form = this._formComponent.form(); if (!form) return; this.setUseCompleteLabel(form); form.statusChanges.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => { this.setUseCompleteLabel(form); }); } setUseCompleteLabel(form) { let requiredControls = 0; const keys = Object.keys(form.controls); keys.forEach(key => { if (this.controlIsRequired(form.controls[key])) requiredControls++; }); const keysLen = keys.length / 2; if (this.isRequired() && requiredControls <= keysLen) { this._useCompleteLabel.set(true); } else { this._useCompleteLabel.set(!this.isRequired() && requiredControls > keysLen); } } setIsRequired() { this._isRequired.set(this.controlIsRequired(this.control())); } controlIsRequired(control) { return control.hasValidator(Validators.required); } getError(errors) { const keys = Object.keys(errors); if (!keys.length) return ''; const error = keys[0]; const data = errors[keys[0]]; switch (error) { case 'required': return 'Este campo es requerido.'; case 'minlength': return `Tiene que tener como mínimo ${data.requiredLength} caracteres.`; case 'maxlength': return `Tiene que tener como máximo ${data.requiredLength} caracteres.`; case 'pattern': return 'La contraseña debe contener al menos una letra mayúscula, una minúscula y un símbolo especial.'; default: return 'Revisa el valor ingresado.'; } } ngOnDestroy() { this.controlView().clear(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmFormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.6", type: GrcmFormFieldComponent, isStandalone: true, selector: "lib-grcm-form-field", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "form-group" }, viewQueries: [{ propertyName: "controlView", first: true, predicate: ["controlView"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "@let errors = control().errors;\r\n@let touched = control().touched;\r\n<label [for]=\"id()\" class=\"form-label\">{{ completeLabel() }}</label>\r\n<div class=\"input-group has-validation form-field-invalid d-block\">\r\n <ng-container #controlView></ng-container>\r\n <div class=\"invalid-feedback d-block\">\r\n @if (touched && errors) {\r\n <p>{{ getError(errors) }}<p>\r\n }\r\n </div>\r\n <!-- @else {\r\n <div class=\"valid-feedback d-block\">\r\n Looks good!\r\n </div>\r\n } -->\r\n</div>\r\n", styles: [":host{margin:0;padding:0;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmFormFieldComponent, decorators: [{ type: Component, args: [{ selector: 'lib-grcm-form-field', imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'form-group' }, template: "@let errors = control().errors;\r\n@let touched = control().touched;\r\n<label [for]=\"id()\" class=\"form-label\">{{ completeLabel() }}</label>\r\n<div class=\"input-group has-validation form-field-invalid d-block\">\r\n <ng-container #controlView></ng-container>\r\n <div class=\"invalid-feedback d-block\">\r\n @if (touched && errors) {\r\n <p>{{ getError(errors) }}<p>\r\n }\r\n </div>\r\n <!-- @else {\r\n <div class=\"valid-feedback d-block\">\r\n Looks good!\r\n </div>\r\n } -->\r\n</div>\r\n", styles: [":host{margin:0;padding:0;width:100%}\n"] }] }] }); class GrcmPlainFormFieldComponent { controlView = viewChild.required('controlView', { read: ViewContainerRef }); control = input.required(); id = input.required(); ngOnDestroy() { this.controlView().clear(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmPlainFormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.6", type: GrcmPlainFormFieldComponent, isStandalone: true, selector: "lib-grcm-plain-form-field", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "controlView", first: true, predicate: ["controlView"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "<ng-container #controlView></ng-container>\r\n", styles: [":host{margin:0;padding:0;width:100%}\n"] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmPlainFormFieldComponent, decorators: [{ type: Component, args: [{ selector: 'lib-grcm-plain-form-field', imports: [], template: "<ng-container #controlView></ng-container>\r\n", styles: [":host{margin:0;padding:0;width:100%}\n"] }] }] }); /* eslint-disable @typescript-eslint/no-explicit-any */ class GrcmInputComponent { _grcmFormComponent = inject(GrcmFormComponent); controlComp = inject(GrcmControlComponent); _destroyRef = inject(DestroyRef); type = input('text'); placeholder = input(''); debounceTimer = input(300); icon = input(); autocomplete = input(true); submitFormOnDebounce = input(false); changeValue = output(); debounce = output(); additionalClasses = input(""); control = computed(() => this.controlComp.control()); id = computed(() => this.controlComp.id()); _value = signal(""); value = this._value.asReadonly(); _disabled = signal(false); disabled = this._disabled.asReadonly(); _debouncer = new Subject(); _inputRef = viewChild("input"); ngOnInit() { this.initialize(); } initialize() { this._debouncer .pipe(takeUntilDestroyed(this._destroyRef), debounceTime(this.debounceTimer())) .subscribe(value => { this.debounce.emit(value); if (this.submitFormOnDebounce()) this._grcmFormComponent.onSubmit(); }); } change(value) { this._onTouched(); this._onChange(value); } onBlur() { this._onTouched(); } _onChange = () => { }; _onTouched = () => { }; registerOnChange(fn) { this._onChange = fn; } registerOnTouched(fn) { this._onTouched = fn; } writeValue(value) { if (typeof value === "string") this.updateValue(value); } updateValue(value) { this._value.set(value); const inputRef = this._inputRef(); if (inputRef) inputRef.nativeElement.value = value; } setDisabledState(isDisabled) { this._disabled.set(isDisabled); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.6", type: GrcmInputComponent, isStandalone: true, selector: "lib-grcm-input", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, debounceTimer: { classPropertyName: "debounceTimer", publicName: "debounceTimer", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, submitFormOnDebounce: { classPropertyName: "submitFormOnDebounce", publicName: "submitFormOnDebounce", isSignal: true, isRequired: false, transformFunction: null }, additionalClasses: { classPropertyName: "additionalClasses", publicName: "additionalClasses", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changeValue: "changeValue", debounce: "debounce" }, viewQueries: [{ propertyName: "_inputRef", first: true, predicate: ["input"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (control()) {\r\n @if (icon()) {\r\n <span class=\"input-group-text\">\r\n <i [ngClass]=\"'bi bi-' + icon()\"></i>\r\n </span>\r\n }\r\n @let validator = control()!.validator;\r\n @let valid = control()!.valid;\r\n @let invalid = control()!.invalid;\r\n @let touched = control()!.touched;\r\n <input\r\n [type]=\"type()\"\r\n [placeholder]=\"placeholder()\"\r\n class=\"form-control\"\r\n [class.is-valid]=\"validator && valid && touched\"\r\n [class.is-invalid]=\"validator && invalid && touched\"\r\n (input)=\"change( input.value )\"\r\n [value]=\"value()\"\r\n [id]=\"id()\"\r\n [attr.disabled]=\"disabled() ? 'disabled' : null\"\r\n [attr.autocomplete]=\"autocomplete() ? 'on' : 'off'\"\r\n (blur)=\"onBlur()\"\r\n [ngClass]=\"additionalClasses()\" #input>\r\n}\r\n\r\n\r\n <!--\r\n [class.is-invalid]=\"control().validator && control().invalid && control().touched\" -->\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmInputComponent, decorators: [{ type: Component, args: [{ selector: 'lib-grcm-input', imports: [CommonModule, ReactiveFormsModule, FormsModule], template: "@if (control()) {\r\n @if (icon()) {\r\n <span class=\"input-group-text\">\r\n <i [ngClass]=\"'bi bi-' + icon()\"></i>\r\n </span>\r\n }\r\n @let validator = control()!.validator;\r\n @let valid = control()!.valid;\r\n @let invalid = control()!.invalid;\r\n @let touched = control()!.touched;\r\n <input\r\n [type]=\"type()\"\r\n [placeholder]=\"placeholder()\"\r\n class=\"form-control\"\r\n [class.is-valid]=\"validator && valid && touched\"\r\n [class.is-invalid]=\"validator && invalid && touched\"\r\n (input)=\"change( input.value )\"\r\n [value]=\"value()\"\r\n [id]=\"id()\"\r\n [attr.disabled]=\"disabled() ? 'disabled' : null\"\r\n [attr.autocomplete]=\"autocomplete() ? 'on' : 'off'\"\r\n (blur)=\"onBlur()\"\r\n [ngClass]=\"additionalClasses()\" #input>\r\n}\r\n\r\n\r\n <!--\r\n [class.is-invalid]=\"control().validator && control().invalid && control().touched\" -->\r\n" }] }] }); /* eslint-disable @typescript-eslint/no-unused-vars */ class GrcmExampleLoginComponent { _responseForm = signal(null); responseForm = this._responseForm.asReadonly(); submitForm = output(); dataForm = { form: { id: 'login' }, controls: { username: createGrcmControl({ component: GrcmInputComponent, formFieldComponent: GrcmFormFieldComponent, value: "", validators: [Validators.required, Validators.minLength(3), Validators.maxLength(10)], args: { control: { debounceTimer: 1000, placeholder: "Escriba su usuario", icon: "person-circle", autocomplete: false, // debounce: (value: string) => { // console.log(value) // } }, formField: { label: "Usuario" } }, classes: { control: "input-group" } }), password: createGrcmControl({ component: GrcmInputComponent, formFieldComponent: GrcmFormFieldComponent, value: "", validators: [Validators.required, Validators.minLength(6), Validators.maxLength(15), Validators.pattern('^(?=.*[a-z])(?=.*[A-Z])(?=.*[-_!@#$%^&*(),.?":{}|<>]).+$')], args: { control: { type: 'password', placeholder: "Escriba su contraseña", icon: "lock", autocomplete: false, }, formField: { label: "Contraseña" } }, classes: { control: "input-group" } }), } }; buildForm(form) { // console.log(form); } onChangeControl(data) { // console.log(data) } onSubmit(data) { const user = { ...data.form.value }; this._responseForm.set(user); this.submitForm.emit(user); } getErrors(errors) { console.log({ errors }); if (!errors) return []; return Object.keys(errors); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmExampleLoginComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.6", type: GrcmExampleLoginComponent, isStandalone: true, selector: "lib-grcm-example-login", outputs: { submitForm: "submitForm" }, ngImport: i0, template: "<lib-grcm-form [data]=\"dataForm\" classes=\"row pb-4\" (buildForm)=\"buildForm($event)\" (formChange)=\"onChangeControl($event)\"\r\n (formSubmit)=\"onSubmit($event)\" [templates]=\"{afterFormTemplate}\">\r\n <!-- <ng-template #before_username>, before_username\r\n nombreeee antes\r\n @if (control.valid) {\r\n V\u00C1LIDO\r\n } @else {\r\n INV\u00C1LIDO\r\n }\r\n </ng-template> -->\r\n <ng-template #afterFormTemplate let-form=\"form\">\r\n <div class=\"invalid-feedback d-block\">\r\n @if (form.errors) {\r\n @for (error of getErrors(form); track $index) {\r\n <p>{{ error }}\r\n <p>\r\n }\r\n }\r\n </div>\r\n <lib-grcm-button label=\"Entrar\" class=\"w-100\" [disabled]=\"form.invalid\" type=\"submit\"></lib-grcm-button>\r\n </ng-template>\r\n</lib-grcm-form>\r\n@if (responseForm()) {\r\n <div class=\"container mt-4\">\r\n <p>Respuesta del formulario</p>\r\n <div class=\"p-2\">\r\n <pre><code class=\"language-javascript\" data-lang=\"js\">{{responseForm() | json }}</code></pre>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".highlight{background-color:#f7f7f9}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.JsonPipe, name: "json" }, { kind: "component", type: GrcmButtonComponent, selector: "lib-grcm-button", inputs: ["label", "title", "disabled", "link", "type", "variant", "outline", "size", "additionalClasses", "icon", "submitter", "fontSizeIcon"], outputs: ["clicked"] }, { kind: "component", type: GrcmFormComponent, selector: "lib-grcm-form", inputs: ["data", "templates"], outputs: ["buildForm", "formSubmit", "formChange"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GrcmExampleLoginComponent, decorators: [{ type: Component, args: [{ selector: 'lib-grcm-example-login', imports: [CommonModule, GrcmButtonComponent, GrcmFormComponent], template: "<lib-grcm-form [data]=\"dataForm\" classes=\"row pb-4\" (buildForm)=\"buildForm($event)\" (formChange)=\"onChangeControl($event)\"\r\n (formSubmit)=\"onSubmit($event)\" [templates]=\"{afterFormTemplate}\">\r\n <!-- <ng-template #before_username>, before_username\r\n nombreeee antes\r\n @if (control.valid) {\r\n V\u00C1LIDO\r\n } @else {\r\n INV\u00C1LIDO\r\n }\r\n </ng-template> -->\r\n <ng-template #afterFormTemplate let-form=\"form\">\r\n <div class=\"invalid-feedback d-block\">\r\n @if (form.errors) {\r\n @for (error of getErrors(form); track $index) {\r\n <p>{{ error }}\r\n <p>\r\n }\r\n }\r\n </div>\r\n <lib-grcm-button label=\"Entrar\" class=\"w-100\" [disabled]=\"form.invalid\" type=\"submit\"></lib-grcm-button>\r\n </ng-template>\r\n</lib-grcm-form>\r\n@if (responseForm()) {\r\n <div class=\"container mt-4\">\r\n <p>Respuesta del formulario</p>\r\n <div class=\"p-2\">\r\n <pre><code class=\"language-javascript\" data-lang=\"js\">{{responseForm() | json }}</code></pre>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".highlight{background-color:#f7f7f9}\n"] }] }] }); /* * Public API Surface of grcm-components */ // UI // COMPONENTS // BUTTON /** * Generated bundle index. Do not edit. */ export { GrcmButtonComponent, GrcmControlComponent, GrcmExampleLoginComponent, GrcmFormComponent, GrcmFormFieldComponent, GrcmInputComponent, GrcmPlainFormFieldComponent, createGrcmControl }; //# sourceMappingURL=grcm-components.mjs.map