@von-development-studio/primeng-form-validation
Version:
Angular + PrimeNG Form Validation directives.
366 lines (358 loc) • 14.6 kB
JavaScript
import * as i0 from '@angular/core';
import { EventEmitter, HostListener, Input, Output, Directive, NgModule } from '@angular/core';
import { NG_VALIDATORS, FormsModule } from '@angular/forms';
import * as i1 from 'primeng/api';
import { MessageService } from 'primeng/api';
const VALIDATION_MESSAGES_EN = {
requiredMessage: 'The field \'${name}\' is required',
equalToMessage: 'The field \'${name}\' is not equal',
manualValMessage: 'The field \'${name}\' is not valid'
};
const VALIDATION_MESSAGES_ES = {
requiredMessage: 'El campo \'${name}\' es requerido',
equalToMessage: 'El campo \'${name}\' no es igual',
manualValMessage: 'El campo \'${name}\' no es válido'
};
const VALIDATION_MESSAGES = {
ngModelRequired: 'You need to add [(ngModel)] into the element',
EN: VALIDATION_MESSAGES_EN,
ES: VALIDATION_MESSAGES_ES
};
class VonPrimengValidationDirective {
element;
renderer;
messageService;
ngModel;
ngModelChange = new EventEmitter();
name;
customName;
required;
requiredMessage;
equalTo;
equalIgnoreCase;
equalToMessage;
manualVal;
manualValMessage;
validator = {};
message = '';
messages = {
requiredMessage: '',
equalToMessage: '',
manualValMessage: '',
};
$label;
constructor(element, renderer, messageService) {
this.element = element;
this.renderer = renderer;
this.messageService = messageService;
}
ngOnInit() {
const $closestFormEl = this.element.nativeElement.form ||
this.getClosestForm(this.element.nativeElement);
const isValidationEn = !$closestFormEl.hasAttribute('validation-es');
this.messages = isValidationEn
? VALIDATION_MESSAGES.EN
: VALIDATION_MESSAGES.ES;
this.$label = $closestFormEl.querySelector(`label[for='${this.name}']`);
if (this.$label) {
this.renderer.addClass(this.$label, 'field__label');
if (this.required) {
this.renderer.addClass(this.$label, 'field__label--required');
}
}
this.renderer.setAttribute(this.element.nativeElement, 'validation', 'true');
this.renderer.addClass(this.element.nativeElement, this.verifyClassName(this.element.nativeElement));
}
validate(formValue) {
this.validator = this.getCustomValidators(formValue.value);
this.runValidation();
return this.validator;
}
executeChangeEvent = (value) => {
if (this.manualVal != null) {
setTimeout(() => {
this.validator = this.getCustomValidators(value);
if (!this.fieldNotValid()) {
this.renderer.removeClass(this.element.nativeElement, 'field__error');
this.renderer.removeClass(this.element.nativeElement, 'ng-invalid');
this.renderer.addClass(this.element.nativeElement, 'ng-valid');
}
}, 10);
}
};
executeValidationEvent = () => {
this.validator = this.getCustomValidators(this.ngModel);
const labelText = this.getLabelText();
const { message, valid } = this.verifyValidationMessage();
if (!valid) {
this.renderer.addClass(this.element.nativeElement, 'field__error');
this.messageService.add({
severity: 'error',
detail: message.replace('${name}', labelText),
});
}
else {
this.renderer.removeClass(this.element.nativeElement, 'field__error');
this.renderer.removeClass(this.element.nativeElement, 'ng-invalid');
this.renderer.addClass(this.element.nativeElement, 'ng-valid');
}
this.element.nativeElement.setAttribute('validation', valid);
};
cleanValidationEvent = () => {
this.renderer.removeClass(this.element.nativeElement, 'field__error');
};
getClosestForm = (element) => {
if (element.tagName === 'FORM' || element.tagName === 'BODY') {
return element;
}
const parent = element.parentElement;
if (parent) {
return this.getClosestForm(parent);
}
return element;
};
getLabelText = () => {
let labelText = this.name || '';
if (this.customName) {
labelText = this.customName;
}
if (this.$label && this.$label.innerText) {
labelText = this.$label.innerText;
}
return labelText;
};
runValidation = () => {
const isNotValid = this.fieldNotValid();
if (isNotValid) {
return;
}
this.renderer.removeClass(this.element.nativeElement, 'field__error');
};
verifyClassName = (element) => {
switch (element.tagName) {
case 'INPUT':
return 'field__input';
case 'TEXTAREA':
return 'field__textarea';
case 'P-DROPDOWN':
return 'field__dropdown';
case 'P-CALENDAR':
return 'field__calendar';
}
return 'field__no-defined';
};
verifyValidationMessage = () => {
let message = '';
let valid = false;
if (this.validator['isEmpty']) {
message = this.requiredMessage || this.messages.requiredMessage;
}
else if (this.validator['isNotEqual']) {
message = this.equalToMessage || this.messages.equalToMessage;
}
else if (this.validator['manualNotValid']) {
message = this.manualValMessage || this.messages.manualValMessage;
}
else {
valid = true;
}
return { message, valid };
};
getCustomValidators = (formValue) => {
return {
...this.validateRequired(formValue),
...this.validateEqualTo(formValue),
...this.validateManual(formValue),
};
};
validateRequired = (value) => {
let validation = {};
if (!this.required) {
return {};
}
if (this.required && (value == null || value === '')) {
validation = { isEmpty: true };
}
return validation;
};
validateEqualTo = (value) => {
if (!this.equalTo) {
return {};
}
let validation = {};
const isNotEqual = this.equalIgnoreCase
? `${value}`.toLowerCase() !== `${this.equalTo}`.toLowerCase()
: value !== this.equalTo;
if (isNotEqual) {
validation = { isNotEqual: true };
}
return validation;
};
validateManual = (_) => {
if (this.manualVal == null || this.manualVal) {
return {};
}
return { manualNotValid: true };
};
fieldNotValid = () => {
return (this.validator['isEmpty'] ||
this.validator['isNotEqual'] ||
this.validator['manualNotValid']);
};
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: VonPrimengValidationDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.MessageService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: VonPrimengValidationDirective, selector: "[validation]", inputs: { ngModel: "ngModel", name: "name", customName: "customName", required: "required", requiredMessage: "requiredMessage", equalTo: "equalTo", equalIgnoreCase: "equalIgnoreCase", equalToMessage: "equalToMessage", manualVal: "manualVal", manualValMessage: "manualValMessage" }, outputs: { ngModelChange: "ngModelChange" }, host: { listeners: { "ngModelChange": "executeChangeEvent($event)", "executeValidation": "executeValidationEvent()", "cleanValidation": "cleanValidationEvent()" } }, providers: [
{
provide: NG_VALIDATORS,
useExisting: VonPrimengValidationDirective,
multi: true,
},
], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: VonPrimengValidationDirective, decorators: [{
type: Directive,
args: [{
selector: '[validation]',
providers: [
{
provide: NG_VALIDATORS,
useExisting: VonPrimengValidationDirective,
multi: true,
},
],
standalone: false,
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.MessageService }], propDecorators: { ngModel: [{
type: Input
}], ngModelChange: [{
type: Output
}], name: [{
type: Input
}], customName: [{
type: Input
}], required: [{
type: Input
}], requiredMessage: [{
type: Input
}], equalTo: [{
type: Input
}], equalIgnoreCase: [{
type: Input
}], equalToMessage: [{
type: Input
}], manualVal: [{
type: Input
}], manualValMessage: [{
type: Input
}], executeChangeEvent: [{
type: HostListener,
args: ['ngModelChange', ['$event']]
}], executeValidationEvent: [{
type: HostListener,
args: ['executeValidation']
}], cleanValidationEvent: [{
type: HostListener,
args: ['cleanValidation']
}] } });
class VonPrimengValidateDirective {
el;
customSubmit = new EventEmitter();
isValid;
isFocused;
constructor(el) {
this.el = el;
}
onSubmitEvent = (e) => {
e.preventDefault();
const elements = this.el.nativeElement.querySelectorAll('[validation]');
this.isValid = true;
this.isFocused = false;
elements.forEach((el) => {
el.dispatchEvent(new Event('executeValidation'));
const elValid = el.getAttribute('validation') === 'true';
if (this.isValid) {
this.isValid = elValid;
}
const ignoreValidity = this.shouldIgnoreValidity(el.tagName);
if (!ignoreValidity) {
const inputEl = this.getInputElement(el);
if (!elValid && !this.isFocused) {
this.isFocused = true;
inputEl.focus();
}
}
});
if (this.isValid) {
this.customSubmit.emit(e);
}
};
onResetEvent = (e) => {
const elements = this.el.nativeElement.querySelectorAll('[validation]');
elements.forEach((el) => {
el.dispatchEvent(new Event('cleanValidation'));
});
};
shouldIgnoreValidity = (tagName) => {
// TODO: Add conditions to ignore validity focus state...
// switch (tagName) {
// case 'P-DROPDOWN':
// case 'P-CALENDAR':
// return true;
// }
return false;
};
getInputElement = (el) => {
if (el.tagName === 'P-CALENDAR' ||
el.tagName === 'P-AUTOCOMPLETE' ||
el.tagName === 'P-DROPDOWN') {
const inputEl = el.querySelector('input');
return inputEl;
}
return el;
};
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: VonPrimengValidateDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: VonPrimengValidateDirective, selector: "[validate]", outputs: { customSubmit: "validate" }, host: { listeners: { "submit": "onSubmitEvent($event)", "reset": "onResetEvent($event)" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: VonPrimengValidateDirective, decorators: [{
type: Directive,
args: [{
selector: '[validate]',
standalone: false,
}]
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { customSubmit: [{
type: Output,
args: ['validate']
}], onSubmitEvent: [{
type: HostListener,
args: ['submit', ['$event']]
}], onResetEvent: [{
type: HostListener,
args: ['reset', ['$event']]
}] } });
class VonPrimengFormModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: VonPrimengFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: VonPrimengFormModule, declarations: [VonPrimengValidateDirective, VonPrimengValidationDirective], imports: [FormsModule], exports: [FormsModule,
VonPrimengValidateDirective,
VonPrimengValidationDirective] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: VonPrimengFormModule, providers: [MessageService], imports: [FormsModule, FormsModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: VonPrimengFormModule, decorators: [{
type: NgModule,
args: [{
declarations: [VonPrimengValidateDirective, VonPrimengValidationDirective],
imports: [FormsModule],
exports: [
FormsModule,
VonPrimengValidateDirective,
VonPrimengValidationDirective,
],
providers: [MessageService],
}]
}] });
/*
* Public API Surface of angular-form-validation
*/
/**
* Generated bundle index. Do not edit.
*/
export { VALIDATION_MESSAGES, VonPrimengFormModule, VonPrimengValidateDirective, VonPrimengValidationDirective };
//# sourceMappingURL=von-development-studio-primeng-form-validation.mjs.map