lc-forms
Version:
Is a library for simplified object-based creation and validation of forms in Angular/Angular Universal. The library is inspired by [angular.io dynamic forms](https://angular.io/docs/ts/latest/cookbook/dynamic-form.html) and [Filip Lauc's](https://github.c
380 lines (379 loc) • 17.8 kB
JavaScript
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, HostBinding, Injectable, Input, NgModule, Output } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
var LCCustomValidators = (function () {
function LCCustomValidators() {
}
/**
* @param {?} key
* @return {?}
*/
LCCustomValidators.match = function (key) {
return function (control) {
if (control.value && control.root.controls) {
return control.root.controls[key].value !== control.value ?
{ 'match': { 'currentValue': control.value, 'requiredValue': control.root.controls[key].value, 'mustMatchField': key }
} : null;
}
else {
return null;
}
};
};
return LCCustomValidators;
}());
var LCFormService = (function () {
function LCFormService() {
}
/**
* @param {?} elements
* @return {?}
*/
LCFormService.prototype.create = function (elements) {
var /** @type {?} */ temp = {}, /** @type {?} */ toReturn = {}, /** @type {?} */ matches = [];
elements.forEach(function (e) {
var /** @type {?} */ val = e.value || '';
var /** @type {?} */ validators = null;
if (e.validation) {
if (Array.isArray(e.validation)) {
validators = [];
e.validation.forEach(function (i) { return validators.push(setValidator(i, e)); });
}
else {
validators = setValidator(e.validation);
}
}
temp[e.key] = new FormControl(val, validators);
});
toReturn['fbGroup'] = new FormGroup(temp);
// Add matches for watching if required
if (matches.length) {
toReturn['matches'] = matches;
}
return toReturn;
/**
* @param {?} item
* @param {?=} original
* @return {?}
*/
function setValidator(item, original) {
switch (item.type) {
case 'required': return Validators.required;
case 'minLength': return Validators.minLength(item.value);
case 'maxLength': return Validators.maxLength(item.value);
case 'pattern': return Validators.pattern(item.value);
case 'match':
matches.push({ toMatch: item.value, model: original.key });
return LCCustomValidators.match(item.value);
}
}
};
return LCFormService;
}());
LCFormService.decorators = [
{ type: Injectable },
];
/**
* @nocollapse
*/
LCFormService.ctorParameters = function () { return []; };
var LCFormComponent = (function () {
/**
* @param {?} _controlGroup
*/
function LCFormComponent(_controlGroup) {
this._controlGroup = _controlGroup;
// Outputs
this.submitted = new EventEmitter();
this.changed = new EventEmitter();
}
Object.defineProperty(LCFormComponent.prototype, "lcFormData", {
/**
* @param {?} value
* @return {?}
*/
set: function (value) {
this._data = value;
this._data.settings = this._setSettings(value.settings);
this.sortElements();
var /** @type {?} */ cg = this._controlGroup.create(this._data.elements);
this._form = cg.fbGroup;
this._matches = cg.matches;
this.comp = {
data: this._data,
form: this._form,
settings: {
singleErrorMessage: this._data.settings.singleErrorMessage,
errorOnDirty: this._data.settings.errorOnDirty,
showValidation: this._data.settings.showValidation,
extraValidation: this._data.settings.submitButtonExtraValidation || true
}
};
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
LCFormComponent.prototype.submit = function () { this.submitted.emit(this._form.value); };
/**
* @param {?} event
* @return {?}
*/
LCFormComponent.prototype.onElementValueChange = function (event) {
if (this._matches) {
// console.log('this._matches: ', this._matches);
var /** @type {?} */ key_1 = Object.keys(event)[0], /** @type {?} */
// See if we should check for matches
mat = this._matches[0].find(function (a) { return a.toMatch === key_1; });
// Update the cg if we found a matcher
if (mat) {
this._form.controls[mat.model].updateValueAndValidity();
}
}
this.changed.emit(event);
};
/**
* @return {?}
*/
LCFormComponent.prototype.sortElements = function () { this._data.elements.sort(function (a, b) { return a.order - b.order; }); };
/**
* @param {?} settings
* @return {?}
*/
LCFormComponent.prototype._setSettings = function (settings) {
var /** @type {?} */ defaultSettings = {
submitButton: true,
submitButtonText: 'Submit',
submitButtonExtraValidation: null,
noteText: null,
noteLabel: null,
showValidation: true,
singleErrorMessage: true,
errorOnDirty: true
};
// Add received settings
if (settings) {
for (var /** @type {?} */ p in defaultSettings) {
if (settings.hasOwnProperty(p)) {
defaultSettings[p] = settings[p];
}
else {
defaultSettings[p] = defaultSettings[p];
}
}
}
return defaultSettings;
};
return LCFormComponent;
}());
LCFormComponent.decorators = [
{ type: Component, args: [{
template: "\n <form [formGroup]=\"comp.form\" [ngClass]=\"comp.data.classes?.form\">\n <lc-element *ngFor=\"let e of comp.data.elements\" [info]=\"{element: e, form: comp.form, settings: comp.settings, classes: comp.data.classes}\" (valueChange)=\"onElementValueChange($event)\"></lc-element>\n <div class=\"row\">\n <div *ngIf=\"comp.data.settings.submitButton\" [ngClass]=\"comp.data.classes?.submit\">\n <button type=\"submit\" [disabled]=\"!comp.form.valid && comp.settings.extraValidation\" [ngClass]=\"comp.data.classes?.submitButton\">{{comp.data.settings.submitButtonText}}</button>\n </div>\n <div *ngIf=\"comp.data.settings.noteText\" [ngClass]=\"comp.data.classes.note\">\n <span *ngIf=\"comp.data.settings.noteLabel\" [ngClass]=\"comp.data.classes.noteLabel\">{{comp.data.settings.noteLabel}}</span> \n {{comp.data.settings.noteText}}\n </div>\n </div>\n </form>\n ",
// tslint:disable-next-line:component-selector
selector: 'lc-form'
},] },
];
/**
* @nocollapse
*/
LCFormComponent.ctorParameters = function () { return [
{ type: LCFormService, },
]; };
LCFormComponent.propDecorators = {
'lcFormData': [{ type: Input },],
'submitted': [{ type: Output },],
'changed': [{ type: Output },],
};
var LCElementComponent = (function () {
function LCElementComponent() {
this.valueChange = new EventEmitter();
this.checkboxIsRequired = false;
}
Object.defineProperty(LCElementComponent.prototype, "toSet", {
/**
* @return {?}
*/
get: function () {
return this.element && this.element.classes && this.element.classes.wrapper ? this.element.classes.wrapper : '';
},
enumerable: true,
configurable: true
});
Object.defineProperty(LCElementComponent.prototype, "info", {
/**
* @param {?} value
* @return {?}
*/
set: function (value) {
this.element = value.element;
this.form = value.form;
this.settings = value.settings;
this.classes = value.classes;
if (this.element.type === 'checkbox') {
this.element.value = !this.element.value ? [] : this.element.value;
this.checkboxIsRequired = this.element.validation && this.element.validation[0].type === 'required';
}
if (this.classes.errors) {
if (!this.element.classes.error) {
this.element.classes.error = this.classes.errors;
}
else {
this.element.classes.error = this.element.classes.error.concat(this.classes.errors);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(LCElementComponent.prototype, "showErrorMsg", {
/**
* @return {?}
*/
get: function () {
return this.settings.errorOnDirty ?
!this.form.controls[this.element.key].valid && !this.form.controls[this.element.key].dirty :
!this.form.controls[this.element.key].valid;
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
LCElementComponent.prototype.errors = function () {
var _this = this;
if (this.element.validation && !this.form.controls[this.element.key].valid) {
var /** @type {?} */ temp_1 = [], /** @type {?} */ errors_1 = this.form.controls[this.element.key].errors, /** @type {?} */ errorKeys = Object.keys(errors_1);
if (this.settings.singleErrorMessage) {
temp_1.push(this._setError(errorKeys[errorKeys.length - 1], errors_1));
}
else {
errorKeys.forEach(function (a) { return temp_1.push(_this._setError(a, errors_1)); });
}
return temp_1;
}
};
/**
* @param {?} option
* @return {?}
*/
LCElementComponent.prototype.setRadio = function (option) {
this.form.controls[this.element.key].setValue(option.value);
this.onValueChange(option.value);
};
/**
* @param {?} option
* @return {?}
*/
LCElementComponent.prototype.setCheckbox = function (option) {
var /** @type {?} */ index = this.element.value.indexOf(option.value);
if (index !== -1) {
this.element.value.splice(index, 1);
}
else {
this.element.value.push(option.value);
}
this.form.controls[this.element.key].setValue(this.element.value);
this.onValueChange(this.element.value);
};
/**
* @return {?}
*/
LCElementComponent.prototype.chackboxValueChange = function () {
var _this = this;
if (this.checkboxIsRequired) {
if (this.element.value.length === 1) {
this.element.options.find(function (a) { return a.value === _this.element.value[0]; }).disabled = true;
}
else {
this.element.options.forEach(function (a) { return a.disabled = false; });
}
}
};
/**
* @param {?} event
* @return {?}
*/
LCElementComponent.prototype.onValueChange = function (event) {
if (this.element.emitChanges !== false) {
this.valueChange.emit((_a = {}, _a[this.element.key] = event, _a));
}
var _a;
};
/**
* @param {?} option
* @return {?}
*/
LCElementComponent.prototype.isSelectActive = function (option) { return this.element.value.find(function (a) { return a === option.value; }) ? true : false; };
/**
* @param {?} item
* @param {?} errors
* @return {?}
*/
LCElementComponent.prototype._setError = function (item, errors) {
var /** @type {?} */ errorMsg = this.element.validation.find(function (a) { return a.type.toLowerCase() === item; }).message;
var /** @type {?} */ tag = this.element.label || this.element.key;
if (!errorMsg) {
switch (item) {
// Set error messages
case 'required':
errorMsg = tag + " is required.";
break;
case 'minlength':
errorMsg = tag + " has to be at least " + errors[item].requiredLength + " characters long.";
break;
case 'maxlength':
errorMsg = tag + " can't be longer then " + errors[item].requiredLength + " characters.";
break;
case 'pattern':
errorMsg = tag + " must match this pattern: " + errors[item].requiredPattern + ".";
break;
case 'match':
errorMsg = tag + " must match the " + errors[item].mustMatchField + " field.";
break;
}
}
return errorMsg;
};
return LCElementComponent;
}());
LCElementComponent.decorators = [
{ type: Component, args: [{
// tslint:disable-next-line:component-selector
selector: 'lc-element',
template: "\n <div [formGroup]=\"form\" [ngClass]=\"element.classes?.group\">\n <label *ngIf=\"element.label\"\n [ngClass]=\"element.classes?.label\"\n [attr.for]=\"element.key\">\n {{element.label}}\n </label>\n <div [ngSwitch]=\"element.type\">\n <select *ngSwitchCase=\"'dropdown'\"\n [formControlName]=\"element.key\"\n (ngModelChange)=\"onValueChange($event)\"\n [ngClass]=\"element.classes?.element\"\n [id]=\"element.key\">\n <option *ngFor=\"let o of element.options\" [value]=\"o.value\">{{o.name ? o.name : o.value}}</option>\n </select>\n\n <div *ngSwitchCase=\"'checkbox'\" [ngClass]=\"element.classes?.element\">\n <div class=\"checkbox\" *ngFor=\"let o of element.options\">\n <input [type]=\"element.type\"\n [formControlName]=\"element.key\"\n [name]=\"element.key\"\n [value]=\"o.value\"\n [checked]=\"isSelectActive(o)\"\n (change)=\"chackboxValueChange()\"\n (click)=\"setCheckbox(o)\">\n <span>{{o.name ? o.name : o.value}}</span>\n </div>\n </div>\n\n <textarea *ngSwitchCase=\"'textarea'\"\n [formControlName]=\"element.key\"\n (ngModelChange)=\"onValueChange($event)\"\n [id]=\"element.key\"\n [attr.placeholder]=\"element.placeholder\"\n [attr.rows]=\"element.rows\"\n [ngClass]=\"element.classes?.element\"></textarea>\n\n <div *ngSwitchCase=\"'radio'\" [ngClass]=\"element.classes?.element\">\n <div class=\"radio\" *ngFor=\"let o of element.options\">\n <input [type]=\"element.type\"\n [formControlName]=\"element.key\"\n [name]=\"element.key\"\n [value]=\"o.value\"\n [checked]=\"element.value === o.value\"\n (click)=\"setRadio(o)\">\n <span>{{o.name ? o.name : o.value}}</span>\n </div>\n </div>\n\n <input *ngSwitchDefault\n [formControlName]=\"element.key\"\n [attr.placeholder]=\"element.placeholder\"\n [type]=\"element.type\"\n (ngModelChange)=\"onValueChange($event)\"\n [ngClass]=\"element.classes?.element\"\n [id]=\"element.key\">\n </div>\n\n <div *ngIf=\"settings.showValidation\" [hidden]=\"showErrorMsg\">\n <span *ngFor=\"let e of errors()\" [ngClass]=\"element.classes?.error\">{{e}}</span>\n </div>\n </div>\n "
},] },
];
/**
* @nocollapse
*/
LCElementComponent.ctorParameters = function () { return []; };
LCElementComponent.propDecorators = {
'toSet': [{ type: HostBinding, args: ['class',] },],
'info': [{ type: Input },],
'valueChange': [{ type: Output },],
};
var LCFormsModule = (function () {
function LCFormsModule() {
}
return LCFormsModule;
}());
LCFormsModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule, ReactiveFormsModule],
declarations: [LCFormComponent, LCElementComponent],
exports: [LCFormComponent, LCElementComponent],
providers: [LCFormService]
},] },
];
/**
* @nocollapse
*/
LCFormsModule.ctorParameters = function () { return []; };
/**
* Generated bundle index. Do not edit.
*/
export { LCFormsModule, LCElementComponent as ɵc, LCFormComponent as ɵa, LCFormService as ɵb };
//# sourceMappingURL=lc-forms.es5.js.map