UNPKG

@ekisa-cdk/forms

Version:

🛠️ Easily build & integrate dynamic forms

199 lines (198 loc) 7.71 kB
import { CheckBox, DatePicker, FieldSet, NumberBox, RadioGroup, SelectBox, TextArea, TextBox, TimePicker } from "../controls"; import { Validators } from "../validators"; export class AutoMapperPlugin { constructor(source, config) { this._source = source; this._config = config; } run() { const source = JSON.parse(JSON.stringify(this._source)); return this._mapFromSource(source); } _mapFromSource(source) { let controls = []; const { keys } = this._config; for (const item of source) { const controlType = item[keys.controlTypePropertyName]; switch (controlType) { case this._config.types["FieldSet"]: { const control = new FieldSet({ legend: item[keys.fieldSet.legend], cols: item[keys.fieldSet.cols], children: this._mapFromSource(item[keys.fieldSet.children]) }); controls = [...controls, control]; break; } case this._config.types["TextBox"]: { const control = new TextBox(item[keys.control.value], { key: item[keys.control.key], label: item[keys.control.label], placeholder: item[keys.control.placeholder], validators: this._mapValidators(item[keys.control.key], item[keys.control.validators]) }); controls.push(control); break; } case this._config.types["TextArea"]: { const control = new TextArea(item[keys.control.value], { key: item[keys.control.key], label: item[keys.control.label], placeholder: item[keys.control.placeholder], cols: item[keys.textAreaOptions.cols], rows: item[keys.textAreaOptions.rows], validators: this._mapValidators(item[keys.control.key], item[keys.control.validators]) }); controls.push(control); break; } case this._config.types["NumberBox"]: { const control = new NumberBox(item[keys.control.value], { key: item[keys.control.key], label: item[keys.control.label], min: item[keys.numberBoxOptions.min], max: item[keys.numberBoxOptions.max], validators: this._mapValidators(item[keys.control.key], item[keys.control.validators]) }); controls.push(control); break; } case this._config.types["SelectBox"]: { const options = item[keys.selectBoxOptions.options].map((o) => ({ value: o[keys.selectBoxOptions.value], text: o[keys.selectBoxOptions.text], meta: o[keys.selectBoxOptions.meta] })); const control = new SelectBox(item[keys.control.value], { key: item[keys.control.key], label: item[keys.control.label], options, validators: this._mapValidators(item[keys.control.key], item[keys.control.validators]) }); controls.push(control); break; } case this._config.types["CheckBox"]: { const control = new CheckBox(item[keys.control.value], { key: item[keys.control.key], label: item[keys.control.label], validators: this._mapValidators(item[keys.control.key], item[keys.control.validators]) }); controls.push(control); break; } case this._config.types["RadioGroup"]: { const items = item[keys.radioGroupOptions.items].map((o) => ({ value: o[keys.radioGroupOptions.value], label: o[keys.radioGroupOptions.label] })); const control = new RadioGroup(item[keys.control.value], { key: item[keys.control.key], text: item[keys.control.label], items, validators: this._mapValidators(item[keys.control.key], item[keys.control.validators]) }); controls.push(control); break; } case this._config.types["DatePicker"]: { const control = new DatePicker(item[keys.control.value], { key: item[keys.control.key], label: item[keys.control.label], validators: this._mapValidators(item[keys.control.key], item[keys.control.validators]) }); controls.push(control); break; } case this._config.types["TimePicker"]: { const control = new TimePicker(item[keys.control.value], { key: item[keys.control.key], label: item[keys.control.label], validators: this._mapValidators(item[keys.control.key], item[keys.control.validators]) }); controls.push(control); break; } default: { throw new Error(`${item[keys.control.key]} -> ${controlType} was not recognized`); } } } return controls; } _mapValidators(controlKey, rules) { if (rules?.length === 0 || rules === null || rules === void 0) return []; if (!Array.isArray(rules)) throw new Error(`${controlKey}: Invalid structure for validators. It must be an array of items`); const { validators: validatorKeys } = this._config.keys; const validators = []; for (const rule of rules) { const ruleType = rule[validatorKeys["name"]]; switch (ruleType) { case "required": validators.push(Validators.required); break; case "requiredTrue": validators.push(Validators.requiredTrue); break; case "email": validators.push(Validators.email); break; case "min": { const valueKey = validatorKeys["value"]; if (!valueKey) throw new Error(`${controlKey}: a value must be provided for the min validator`); const value = rule[valueKey]; if (typeof value !== "number") throw new Error(`${controlKey}: type ${typeof value} is invalid for the min validator`); validators.push(Validators.min(value)); break; } case "max": { const valueKey = validatorKeys["value"]; if (!valueKey) throw new Error(`${controlKey}: a value must be provided for the max validator`); const value = rule[valueKey]; if (typeof value !== "number") throw new Error(`${controlKey}: type ${typeof value} is invalid for the max validator`); validators.push(Validators.max(value)); break; } case "minLength": { const valueKey = validatorKeys["value"]; if (!valueKey) throw new Error(`${controlKey}: a value must be provided for the minLength validator`); const value = rule[valueKey]; if (typeof value !== "number") throw new Error(`${controlKey}: type ${typeof value} is invalid for the minLength validator`); validators.push(Validators.minLength(value)); break; } case "maxLength": { const valueKey = validatorKeys["value"]; if (!valueKey) throw new Error(`${controlKey}: a value must be provided for the maxLength validator`); const value = rule[valueKey]; if (typeof value !== "number") throw new Error(`${controlKey}: type ${typeof value} is invalid for the maxLength validator`); validators.push(Validators.maxLength(value)); break; } default: throw new Error(`Invalid validator ${JSON.stringify(rule)} for "${controlKey}" control. The configured name is "${validatorKeys["name"]}"`); } } return validators; } }