UNPKG

@formql/core

Version:

FormQL - A framework for building dynamic forms

1,064 lines (1,053 loc) 117 kB
import { __decorate, __metadata, __assign, __spread, __param } from 'tslib'; import { Input, Output, Component, EventEmitter, Injectable, ComponentFactoryResolver, ɵɵdefineInjectable, ɵɵinject, Inject, Directive, ViewChild, ViewContainerRef, ChangeDetectionStrategy, ElementRef, Renderer2, TemplateRef, HostListener, forwardRef, NgModule } from '@angular/core'; import { FormGroup, FormControl, FormBuilder, NG_VALUE_ACCESSOR, NG_VALIDATORS, Validators, ReactiveFormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { UUID } from 'angular2-uuid'; import { Subject } from 'rxjs'; import { map, concatMap, takeUntil } from 'rxjs/operators'; import { TextMaskModule } from 'angular2-text-mask'; import { createAutoCorrectedDatePipe, createNumberMask } from 'text-mask-addons'; var ContainerType; (function (ContainerType) { ContainerType[ContainerType["Section"] = 1] = "Section"; ContainerType[ContainerType["Component"] = 2] = "Component"; ContainerType[ContainerType["Page"] = 3] = "Page"; })(ContainerType || (ContainerType = {})); var FormQLMode; (function (FormQLMode) { FormQLMode[FormQLMode["View"] = 0] = "View"; FormQLMode[FormQLMode["Edit"] = 1] = "Edit"; })(FormQLMode || (FormQLMode = {})); var PlainLayoutComponent = /** @class */ (function () { function PlainLayoutComponent() { this.submit = new EventEmitter(); } PlainLayoutComponent.prototype.onSubmitTriggered = function () { this.submit.emit(null); }; PlainLayoutComponent.componentName = 'PlainLayoutComponent'; __decorate([ Input(), __metadata("design:type", Object) ], PlainLayoutComponent.prototype, "form", void 0); __decorate([ Input(), __metadata("design:type", FormGroup) ], PlainLayoutComponent.prototype, "reactiveForm", void 0); __decorate([ Input(), __metadata("design:type", Number) ], PlainLayoutComponent.prototype, "mode", void 0); __decorate([ Output(), __metadata("design:type", Object) ], PlainLayoutComponent.prototype, "submit", void 0); PlainLayoutComponent = __decorate([ Component({ selector: 'formql-plain-layout', template: "<ng-container *ngIf=\"form && form.pages && form.pages.length > 0\">\n <form [formGroup]=\"reactiveForm\" (ngSubmit)=\"onSubmitTriggered()\">\n <div formql-page-wrapper *ngIf=\"form.pages\"\n [(page)]=\"form.pages[0]\"\n [reactivePage]=\"reactiveForm.controls[form.pages[0].pageId]\"\n [formGroupName]=\"form.pages[0].pageId\"\n [mode]=\"mode\"></div>\n </form>\n </ng-container>" }) ], PlainLayoutComponent); return PlainLayoutComponent; }()); var DndService = /** @class */ (function () { function DndService() { } DndService.prototype.synchroniseSectionModel = function (page, event) { var sourceSection = page.sections.find(function (s) { return s.sectionId === event.sourceWrapperId; }); var sourceComponent = null; if (event.sourceObjectId === 'new') { sourceComponent = this.newComponent(); event.sourceObjectId = sourceComponent.componentId; sourceSection = page.sections.find(function (s) { return s.sectionId === event.targetWrapperId; }); if (sourceSection) sourceSection.components.push(sourceComponent); else return page; // this should never happen } else sourceComponent = sourceSection.components.find(function (c) { return c.componentId === event.sourceObjectId; }); if (!sourceComponent) return; // has the component been moved across position type (header/body)? if (sourceComponent.position.type !== event.positionType) sourceComponent.position.type = event.positionType; // has the component been placed in a differnet CSS grid area? if (sourceComponent.position.id !== event.targetPositionId) sourceComponent.position.id = event.targetPositionId; if (event.sourceWrapperId !== event.targetWrapperId) { var targetSection = this.transferComponent(page, sourceSection, event); targetSection.template.reRender = true; targetSection = this.reorderComponents(targetSection, sourceComponent, event); } else sourceSection = this.reorderComponents(sourceSection, sourceComponent, event); sourceSection.template.reRender = true; return page; }; DndService.prototype.synchronisePageModel = function (page, event) { var sourceSection = null; if (event.sourceObjectId === 'new') { sourceSection = this.newSection(); page.sections.push(sourceSection); } else sourceSection = page.sections.find(function (s) { return s.sectionId === event.sourceObjectId; }); // can't find the source section, model must be in different page if (sourceSection != null) { if (sourceSection.position.id !== event.targetPositionId) sourceSection.position.id = event.targetPositionId; page.template.reRender = true; page = this.reorderSections(page, sourceSection, event); } return page; }; DndService.prototype.reorderComponents = function (section, sourceCompoment, event) { var components = section.components.filter(function (c) { return c.position.id === sourceCompoment.position.id; }); var targetComponent = components.find(function (c) { return c.componentId === event.targetIndexId; }); if (targetComponent) { sourceCompoment.position.index = targetComponent.position.index; targetComponent.position.index = targetComponent.position.index + 0.5; } components = components.sort(function (left, right) { return left.position.index - right.position.index; }); for (var i = 0; i < components.length; i++) { components[i].position.index = i; } return section; }; DndService.prototype.reorderSections = function (page, sourceSection, event) { var sections = page.sections.filter(function (c) { return c.position.id === sourceSection.position.id; }); var targetSection = sections.find(function (c) { return c.sectionId === event.targetIndexId; }); if (targetSection) { sourceSection.position.index = targetSection.position.index; targetSection.position.index = targetSection.position.index + 0.5; } sections = sections.sort(function (left, right) { return left.position.index - right.position.index; }); for (var i = 0; i < sections.length; i++) sections[i].position.index = i; return page; }; DndService.prototype.transferComponent = function (page, sourceSection, event) { var targetSection = page.sections.find(function (s) { return s.sectionId === event.targetWrapperId; }); if (!targetSection) return null; var component = sourceSection.components.find(function (c) { return c.componentId === event.sourceObjectId; }); if (!component) return null; var index = sourceSection.components.findIndex(function (s) { return s.componentId === event.sourceObjectId; }); targetSection.components.push(component); sourceSection.components.splice(index, 1); return targetSection; }; DndService.prototype.newSection = function () { return { sectionId: UUID.UUID(), sectionName: 'New section', components: [], template: { header: { gridTemplateColumns: '1fr', gridTemplateRows: '1fr', gridTemplateAreas: '"ID1_1"' }, body: { gridTemplateColumns: '1fr', gridTemplateRows: '1fr', gridTemplateAreas: '"ID1_1"' } }, position: { id: '-1', index: 0 } }; }; DndService.prototype.newComponent = function () { return { componentId: UUID.UUID(), label: 'New Component', componentName: 'FormQLLabelComponent', position: { id: '-1', index: 0 } }; }; DndService = __decorate([ Injectable() ], DndService); return DndService; }()); var GridPositionType; (function (GridPositionType) { GridPositionType[GridPositionType["Header"] = 1] = "Header"; GridPositionType[GridPositionType["Body"] = 2] = "Body"; GridPositionType[GridPositionType["Footer"] = 3] = "Footer"; })(GridPositionType || (GridPositionType = {})); var InternalEventType; (function (InternalEventType) { // Editing events InternalEventType[InternalEventType["EditingComponent"] = 1] = "EditingComponent"; InternalEventType[InternalEventType["EditingSection"] = 2] = "EditingSection"; InternalEventType[InternalEventType["EditingPage"] = 3] = "EditingPage"; InternalEventType[InternalEventType["EditingForm"] = 4] = "EditingForm"; InternalEventType[InternalEventType["RemoveComponent"] = 5] = "RemoveComponent"; InternalEventType[InternalEventType["RemoveSection"] = 6] = "RemoveSection"; InternalEventType[InternalEventType["RemovePage"] = 7] = "RemovePage"; // Form changes InternalEventType[InternalEventType["DndFormChanged"] = 8] = "DndFormChanged"; })(InternalEventType || (InternalEventType = {})); var ComponentResolverService = /** @class */ (function () { function ComponentResolverService(componentFactoryResolver) { this.componentFactoryResolver = componentFactoryResolver; this.componentRegister = {}; } ComponentResolverService.prototype.resolveComponent = function (componentName) { if (!this.componentRegister) { return null; } var component = this.componentRegister[componentName]; if (!component) { console.log("Component " + componentName + " not found."); return null; } var resolvedComponent = this.componentFactoryResolver.resolveComponentFactory(component); return resolvedComponent; }; ComponentResolverService.prototype.addComponents = function () { var _this = this; var components = []; for (var _i = 0; _i < arguments.length; _i++) { components[_i] = arguments[_i]; } if (Array.isArray(components)) { components.forEach(function (c) { return _this.componentRegister[c.componentName] = c; }); } }; ComponentResolverService.prototype.addComponent = function (component) { this.componentRegister[component.componentName] = component; }; ComponentResolverService.prototype.getComponentArray = function () { var _this = this; return Array.from(Object.keys(this.componentRegister), function (x) { return _this.componentRegister[x]; }); }; ComponentResolverService = __decorate([ Injectable(), __metadata("design:paramtypes", [ComponentFactoryResolver]) ], ComponentResolverService); return ComponentResolverService; }()); var HelperService = /** @class */ (function () { function HelperService() { } HelperService_1 = HelperService; HelperService.evaluateCondition = function (condition, data) { var response = { value: false, error: null }; if (condition && condition.trim() !== '' && condition !== 'false') { if (condition === 'true') { response.value = true; return response; } if (!data) return response; response = __assign({}, this.evaluate(condition, data)); if (response.value !== true) response.value = false; } return response; }; HelperService.evaluateValue = function (path, data) { var response = { value: null, error: null }; if (!data) return response; response = __assign({}, this.evaluate(path, data)); if (Number.isNaN(response.value) || response.value === Infinity) response.value = null; else response.value = this.deepCopy(response.value); return response; }; HelperService.evaluate = function (path, data) { var response = { value: null, error: null }; var props = Object.keys(data); var params = []; for (var i = 0; i < props.length; i++) params.push(data[props[i]]); params.push(path); props.push('path'); var expression = "\n 'use strict'\n let window = undefined;\n let document = undefined;\n let alert = undefined;\n let a = undefined;\n return " + path + ";\n "; props.push(expression); try { var evalFunc = new (Function.bind.apply(Function, __spread([void 0], props)))(); response.value = evalFunc.apply(void 0, __spread(params)); } catch (err) { response.error = err; } return response; }; HelperService.setValue = function (schema, value, data) { if (value === undefined) value = null; if (schema) { if (!data) data = {}; var key = schema; if (schema.indexOf('.') !== -1) { var arr = schema.split('.'); var item = data; for (var i = 0; i <= arr.length - 1; i++) { key = arr[i]; if (!item[key]) item[key] = {}; if (i !== arr.length - 1) item = item[key]; } item[key] = value; } else data[key] = value; } return data; }; HelperService.getValue = function (schema, data, type) { if (!schema || !data || (data && Object.keys(data).length === 0 && data.constructor === Object)) return; try { var evalFunc = new Function('data', "return data." + schema + ";"); return HelperService_1.resolveType(evalFunc(data), type); } catch (err) { return null; } }; HelperService.setValidators = function (componentResolverService, component, control) { var componentRef = componentResolverService.resolveComponent(component.componentName); if (!componentRef) return control; var type = componentRef.componentType; if (type && (!type['validators'] || (type['validators'] && type['validators'].length === 0))) return control; var validators = []; var rules = component.rules; if (rules != null) { var FormValidators_1 = type['validators']; Object.keys(rules).forEach(function (key) { var item = rules[key]; if (item.value && item.key !== 'readonly' && item.key !== 'hidden' && item.key !== 'value') { var validator = FormValidators_1.find(function (x) { return x.key === item.key; }); if (validator && validator.validator) validators.push(validator.validator); } else if (item.value && item.key === 'readonly' && control.enabled) control.disable(); }); if (control.disabled && (!rules || (rules && !rules.readonly) || (rules && rules.readonly && !rules.readonly.value))) control.enable(); } if (validators.length > 0) control.setValidators(validators); return control; }; HelperService.createReactiveFormStructure = function (form, initialiseData, data) { var _this = this; if (initialiseData === void 0) { initialiseData = true; } if (data === void 0) { data = null; } var formControls = {}; var components = {}; var pageGroup = new FormGroup({}); form.pages.forEach(function (page) { var sectionGroup = {}; if (page.sections != null) page.sections.forEach(function (section) { var componentGroup = {}; if (section.components != null) section.components.forEach(function (component) { components[component.componentId] = component; var singleComponentGroup = new FormControl(); formControls[component.componentId] = singleComponentGroup; componentGroup[component.componentId] = singleComponentGroup; if (initialiseData) { if (!data) data = {}; data = HelperService_1.instantiateData(data, component.schema); try { var value = _this.getValue(component.schema, data, component.type); if (value) { formControls[component.componentId].setValue(value); component.value = value; } } catch (err) { throw err; } } }); sectionGroup[section.sectionId] = new FormGroup(componentGroup); }); pageGroup[page.pageId] = new FormGroup(sectionGroup); }); return { pageGroup: pageGroup, formControls: formControls, components: components, data: data }; }; HelperService.instantiateData = function (data, schema) { if (schema && schema.indexOf('.') !== -1) { var arr = schema.split('.'); var item = data; var key = ''; for (var i = 0; i <= arr.length - 2; i++) { key = arr[i]; if (!item[key]) item[key] = {}; if (i !== arr.length - 2) item = item[key]; } } return data; }; HelperService.deepCopy = function (oldObj, ignoreProperty) { if (ignoreProperty === void 0) { ignoreProperty = null; } var newObj = oldObj; if (oldObj && typeof oldObj === 'object') { newObj = Object.prototype.toString.call(oldObj) === '[object Array]' ? [] : {}; var _loop_1 = function (i) { if (!ignoreProperty || (ignoreProperty && !ignoreProperty.find(function (p) { return p === i; }))) newObj[i] = this_1.deepCopy(oldObj[i]); }; var this_1 = this; for (var i in oldObj) { _loop_1(i); } } return newObj; }; HelperService.propertyCopy = function (source, target, ignoreProperties) { if (ignoreProperties === void 0) { ignoreProperties = null; } if (source && typeof source === 'object') { var _loop_2 = function (i) { if (!ignoreProperties || (ignoreProperties && !ignoreProperties.find(function (p) { return p === i; }))) if (source[i] && typeof source[i] === 'object') { if (!target[i]) target[i] = {}; target[i] = this_2.propertyCopy(source[i], target[i]); } else target[i] = source[i]; else console.log("propertyCopy function doesn't support primitives"); }; var this_2 = this; for (var i in source) { _loop_2(i); } } return target; }; HelperService.formatForGraphQl = function (obj) { var _this = this; var updatedData = this.deepCopy(obj); if (updatedData['__typename']) delete updatedData['__typename']; var dataForQuery = ''; Object.keys(updatedData).forEach(function (fieldName) { if (updatedData[fieldName] == null) dataForQuery += fieldName + ': null,'; else if (typeof updatedData[fieldName] === 'object') dataForQuery += _this.formatForGraphQl(updatedData[fieldName]); else if (typeof updatedData[fieldName] === 'number' || typeof updatedData[fieldName] === 'boolean') dataForQuery += fieldName + (":" + updatedData[fieldName] + ","); else dataForQuery += fieldName + (":\"" + updatedData[fieldName] + ","); }); dataForQuery = "{" + dataForQuery.slice(0, -1) + "}"; return dataForQuery; }; HelperService.formatError = function (error) { if (!error) return; if (error.error && error.error.message) error.message = error.error.message; return error; }; HelperService.resolveType = function (value, type) { if (value === null || value === undefined || value === '') return null; else if (Number.isNaN(value)) return 0; switch (type) { case 'number': if (typeof value === 'string') value = value.replace(/[^\d\.]/g, ''); return Number(value); default: return value; } }; HelperService.maskToArray = function (mask) { var result = []; if (mask) { var maskTrimmed = mask.trim().substring(1).slice(0, -1).replace('\\\\', '\\'); var arry = maskTrimmed.split(','); arry.forEach(function (item) { result.push(item.trim().replace(/\"/g, '').replace(/\'/g, '')); }); } return result; }; HelperService.updateTemplates = function (form) { form.pages.forEach(function (page) { page.template.reRender = false; page.template = HelperService_1.deepCopy(page.template); page.sections.forEach(function (section) { section.template.reRender = false; section.template = HelperService_1.deepCopy(section.template); }); }); return form; }; HelperService.resetValidators = function (components, formControls, componentResolverService) { if (components && Object.keys(components).length > 0) Object.keys(components).forEach(function (key) { var component = components[key]; if (component) { var componentControl = formControls[component.componentId]; if (componentControl) componentControl = HelperService_1.setValidators(componentResolverService, component, componentControl); } }); return formControls; }; HelperService.validateForm = function (formGroup) { var _this = this; Object.keys(formGroup.controls).forEach(function (field) { var control = formGroup.get(field); if (control instanceof FormControl) control.markAsTouched({ onlySelf: true }); else if (control instanceof FormGroup) _this.validateForm(control); }); }; var HelperService_1; HelperService.ɵprov = ɵɵdefineInjectable({ factory: function HelperService_Factory() { return new HelperService(); }, token: HelperService, providedIn: "root" }); HelperService = HelperService_1 = __decorate([ Injectable({ providedIn: 'root' }) ], HelperService); return HelperService; }()); var RuleLogic = /** @class */ (function () { function RuleLogic() { this.evalFunctions = ['GET', 'SUM']; } /* Perform a condition evaluation */ RuleLogic.prototype.doEval = function (condition, conditionFunctions) { var conditionFunctionsDeclares = Object.keys(conditionFunctions).map(function (x) { return "let " + x + " = conditionFunctions." + x + "; "; }).join(''); if (condition.trim() === '') return; if (this.evalFunctions.indexOf(condition.trim()) !== -1) throw Error("Funcitons need a parameter (e.g. GET('contact.firstName') )"); var props = []; var params = []; params.push(condition); params.push(conditionFunctions); props.push('condition'); props.push('conditionFunctions'); var expression = "\n 'use strict'\n " + conditionFunctionsDeclares + "\n let window = undefined;\n let document = undefined;\n let alert = undefined;\n let a = undefined;\n return " + condition + ";\n "; props.push(expression); try { var evalFunc = new (Function.bind.apply(Function, __spread([void 0], props)))(); var response = evalFunc.apply(void 0, __spread(params)); return response; } catch (err) { debugger; // intentionally left to help troubleshooting issues console.log(err); throw err; } }; /* Reset all dependancies for any given condition in a component */ RuleLogic.prototype.resetDependancies = function (formState, condition, component) { var self = this; var registerFunctions = { GET: function (schema) { formState.components = self.setDependents(formState.components, schema, component.componentId); }, SUM: function () { var schemas = []; for (var _i = 0; _i < arguments.length; _i++) { schemas[_i] = arguments[_i]; } schemas.forEach(function (schema) { return formState.components = self.setDependents(formState.components, schema, component.componentId); }); } }; return this.doEval(condition, registerFunctions); }; /* Evaluetes the value of any given condition */ RuleLogic.prototype.evaluate = function (data, condition) { var self = this; var evalFunctions = { GET: function (schema) { var result = self.getSchemaValue(data, schema); if (result !== undefined && result !== null) return result; else return ''; }, SUM: function () { var schemas = []; for (var _i = 0; _i < arguments.length; _i++) { schemas[_i] = arguments[_i]; } var total = 0; schemas.forEach(function (schema) { var value = self.getSchemaValue(data, schema); if (value && !isNaN(value)) total += value; }); return total; } }; return this.doEval(condition, evalFunctions); }; RuleLogic.prototype.evaluateCondition = function (data, condition) { var response = { value: false, error: null }; if (condition && condition.trim() !== '' && condition !== 'false') { if (condition === 'true') { response.value = true; return response; } if (!data) return response; try { response.value = this.evaluate(data, condition); } catch (err) { response.error = err; } if (response.value !== true) response.value = false; } return response; }; RuleLogic.prototype.evaluateValue = function (data, expression) { var response = { value: null, error: null }; if (!data) return response; try { response.value = this.evaluate(data, expression); } catch (err) { response.error = err; return response; } if (Number.isNaN(response.value) || response.value === Infinity) response.value = null; else response.value = HelperService.deepCopy(response.value); return response; }; RuleLogic.prototype.getSchemaValue = function (data, schema) { var evalFunc = new Function('data', 'schema', "return data." + schema); return evalFunc(data, schema); }; RuleLogic.prototype.setDependents = function (components, schema, componentId) { Object.keys(components).forEach(function (key) { var component = components[key]; if (component.schema === schema) { if (!component.dependents) component.dependents = [componentId]; else if (component.dependents.indexOf(componentId) === -1) component.dependents.push(componentId); } }); return components; }; return RuleLogic; }()); var FormService = /** @class */ (function () { function FormService(srv, componentResolverService, formBuilder) { this.componentResolverService = componentResolverService; this.formBuilder = formBuilder; this.ruleLogic = new RuleLogic(); this.injectedService = srv; } FormService.prototype.getFormAndData = function (formName, ids) { var _this = this; if (ids) return this.injectedService.getForm(formName).pipe(map(function (response) { return response; }), concatMap(function (model) { return _this.injectedService.getData(model.dataSource, ids).pipe(map(function (data) { return _this.initialiseFormState(model, data); })); })); else return this.injectedService.getForm(formName).pipe(map(function (model) { return _this.initialiseFormState(model, null); })); }; /* Invokes the form save in the injected service (see constructor for service) */ FormService.prototype.saveForm = function (name, form) { // remove all transactional data var updateForm = HelperService.deepCopy(form); updateForm.pages.forEach(function (page) { page.sections.forEach(function (section) { section.components.forEach(function (component) { Object.keys(component) .filter(function (key) { return component[key] === null; }) .forEach(function (key) { return delete component[key]; }); delete component.value; if (component.rules) if (Object.keys(component.rules).length === 0 && component.rules.constructor === Object) delete component.rules; else Object.keys(component.rules).forEach(function (p) { delete component.rules[p].value; }); }); }); }); return this.injectedService.saveForm(name, updateForm).pipe(map(function (response) { return response; })); }; /* Invokes the data save in the injected service (see constructor for service) */ FormService.prototype.saveData = function (dataSource, ids, data) { return this.injectedService.saveData(dataSource, ids, data).pipe(map(function (result) { return result; })); }; /* Updates a component value and recalculates all dependents If reset is set to true, it will recalculate all dependents, this is when a rules as been modified in the FormQL Editor */ FormService.prototype.updateComponent = function (component, formState, reset) { var _this = this; if (reset === void 0) { reset = false; } var value = HelperService.resolveType(component.value, component.type); formState.data = HelperService.setValue(component.schema, value, formState.data); if (reset) this.resetComponentDependents(formState); // refresh any dependent components if (component.dependents) component.dependents.forEach(function (key) { formState.components[key] = _this.resolveComponentRules(formState.components[key], formState); }); // set the value on any components that have the same schema Object.keys(formState.components).forEach(function (key) { var c = formState.components[key]; if (c.schema === component.schema) try { c.value = HelperService.getValue(c.schema, formState.data, c.type); } catch (err) { throw err; } }); return formState; }; /* Initialises Form State */ FormService.prototype.initialiseFormState = function (form, data) { var reactiveFormStructure = HelperService.createReactiveFormStructure(form, true, data); var formState = { components: reactiveFormStructure.components, data: __assign({}, reactiveFormStructure.data), form: form, formControls: reactiveFormStructure.formControls, reactiveForm: this.formBuilder.group(reactiveFormStructure.pageGroup) }; return this.resolveConditions(formState); }; /* Resets all component dependents, it should only be called when a user modified a question in the formql editor */ FormService.prototype.resetComponentDependents = function (formState) { var _this = this; if (formState.components) { Object.keys(formState.components).forEach(function (componentKey) { return delete formState.components[componentKey].dependents; }); Object.keys(formState.components).forEach(function (componentKey) { var component = formState.components[componentKey]; if (component.rules) Object.keys(component.rules).forEach(function (ruleKey) { var rule = component.rules[ruleKey]; _this.ruleLogic.resetDependancies(formState, rule.condition, component); }); }); Object.keys(formState.components).forEach(function (componentKey) { return (formState.components[componentKey] = _this.resolveComponentRules(formState.components[componentKey], formState)); }); } }; FormService.prototype.getData = function (query, ids) { return this.injectedService.getData(query, ids).pipe(map(function (data) { if (data) return data; else return {}; })); }; FormService.prototype.getForms = function () { return this.injectedService.getForms().pipe(map(function (data) { return data; })); }; FormService.prototype.getForm = function (name) { return this.injectedService.getForm(name).pipe(map(function (data) { return data; })); }; /* Resolve all rules for any given component */ FormService.prototype.resolveComponentRules = function (component, formState) { var _this = this; if (component.rules) { var resetValidator_1 = false; Object.keys(component.rules).forEach(function (key) { var property = component.rules[key]; if (property.condition) { resetValidator_1 = true; var evaluatedValue = _this.ruleLogic.evaluate(formState.data, property.condition); if (key === 'value') { var value = HelperService.resolveType(evaluatedValue, component.type); if (component.value !== value) { component.value = value; formState = _this.updateComponent(component, formState); } } property.value = evaluatedValue; } else delete component.rules[key]; }); if (resetValidator_1) formState.formControls[component.componentId] = HelperService.setValidators(this.componentResolverService, component, formState.formControls[component.componentId]); } return component; }; /* Resolves all conditions in each component, used when initialising the form */ FormService.prototype.resolveConditions = function (formState) { var _this = this; if (formState.components) { var components_1 = formState.components; Object.keys(components_1).forEach(function (componentKey) { return (components_1[componentKey] = _this.resolveComponentRules(components_1[componentKey], formState)); }); } return formState; }; FormService.ɵprov = ɵɵdefineInjectable({ factory: function FormService_Factory() { return new FormService(ɵɵinject("FormQLService"), ɵɵinject(ComponentResolverService), ɵɵinject(FormBuilder)); }, token: FormService, providedIn: "root" }); FormService = __decorate([ Injectable({ providedIn: 'root' }), __param(0, Inject('FormQLService')), __metadata("design:paramtypes", [Object, ComponentResolverService, FormBuilder]) ], FormService); return FormService; }()); var StoreService = /** @class */ (function () { function StoreService(formService, componentResolverService, formBuilder) { this.formService = formService; this.componentResolverService = componentResolverService; this.formBuilder = formBuilder; this.data$ = new Subject(); this.formState$ = new Subject(); this.serviceDestroyed = new Subject(); } // private formControls: FormControls; StoreService.prototype.ngOnDestroy = function () { this.data$.complete(); this.data$.unsubscribe(); }; StoreService.prototype.getData = function () { return this.data$.asObservable(); }; StoreService.prototype.getFormState = function () { return this.formState$.asObservable(); }; StoreService.prototype.updateComponent = function (component) { this.formState = this.formService.updateComponent(component, this.formState, false); this.data$.next(__assign({}, this.formState.data)); this.formState$.next(__assign({}, this.formState)); }; StoreService.prototype.setComponent = function (component) { this.formState = this.formService.updateComponent(component, this.formState, true); // this.formControls = HelperService.resetValidators(this.formState.components, this.formControls, this.componentResolverService); this.data$.next(__assign({}, this.formState.data)); this.formState$.next(__assign({}, this.formState)); }; StoreService.prototype.getAll = function (formName, ids, mode) { var _this = this; this.formService.getFormAndData(formName, ids).pipe(takeUntil(this.serviceDestroyed)).subscribe(function (response) { _this.formState = __assign({}, response); _this.formState.ids = ids; _this.formState.mode = mode; _this.data$.next(__assign({}, response.data)); _this.formState$.next(_this.formState); }, function (error) { _this.formState$.next({ form: { error: HelperService.formatError({ title: 'Error loading form or data', error: error }) } }); }); }; StoreService.prototype.saveForm = function () { this.formService.saveForm(this.formState.form.formName, this.formState.form); }; StoreService.prototype.saveData = function () { return this.formService.saveData(this.formState.form.dataSource, this.formState.ids, this.formState.data); }; StoreService.prototype.validateForm = function () { HelperService.validateForm(this.formState.reactiveForm); }; StoreService.prototype.isFormValid = function () { return this.formState.reactiveForm.valid; }; StoreService.prototype.unsubscribeAll = function () { this.serviceDestroyed.next(); this.serviceDestroyed.complete(); }; StoreService.prototype.reSetForm = function (eventType, event) { switch (eventType) { case InternalEventType.EditingForm: this.populateReactiveForm(); break; case InternalEventType.DndFormChanged: var pageId_1 = event.pageId; var indexDnd = this.formState.form.pages.findIndex(function (p) { return p.pageId === pageId_1; }); if (indexDnd >= 0) this.formState.form.pages[indexDnd] = event; this.populateReactiveForm(); break; case InternalEventType.RemoveComponent: var componentId_1 = event.componentId; var updateSectionId_1 = ''; this.formState.form.pages.forEach(function (page) { page.sections.forEach(function (section) { var indexComponent = section.components.findIndex(function (c) { return c.componentId === componentId_1; }); if (indexComponent >= 0) { section.components.splice(indexComponent, 1); updateSectionId_1 = section.sectionId; } }); }); this.populateReactiveForm(); break; case InternalEventType.RemoveSection: var sectionId_1 = event.sectionId; var updatePageId_1 = ''; this.formState.form.pages.forEach(function (page) { var indexSection = page.sections.findIndex(function (c) { return c.sectionId === sectionId_1; }); if (indexSection >= 0) { page.sections.splice(indexSection, 1); updatePageId_1 = page.pageId; } }); this.populateReactiveForm(); break; } this.formState$.next(__assign({}, this.formState)); }; StoreService.prototype.populateReactiveForm = function () { var _this = this; if (this.formState.form.pages != null && this.formState.form.pages.length > 0) { // get reactive structure -> formControls, pageGroup and components if it's an update var reactiveFormStructure_1 = HelperService.createReactiveFormStructure(this.formState.form, true, this.formState.data); this.formState.formControls = reactiveFormStructure_1.formControls; // if it's an update, refresh reactive form, set all form controls, validators this.formState.form.pages.forEach(function (page) { _this.formState.reactiveForm.setControl(page.pageId, reactiveFormStructure_1.pageGroup[page.pageId]); }); this.formState.form = HelperService.updateTemplates(this.formState.form); if (reactiveFormStructure_1.components != null && Object.keys(reactiveFormStructure_1.components).length > 0) this.formState.formControls = HelperService.resetValidators(reactiveFormStructure_1.components, this.formState.formControls, this.componentResolverService); this.formState = this.formService.resolveConditions(this.formState); } }; StoreService.ɵprov = ɵɵdefineInjectable({ factory: function StoreService_Factory() { return new StoreService(ɵɵinject(FormService), ɵɵinject(ComponentResolverService), ɵɵinject(FormBuilder)); }, token: StoreService, providedIn: "root" }); StoreService = __decorate([ Injectable({ providedIn: 'root' }), __metadata("design:paramtypes", [FormService, ComponentResolverService, FormBuilder]) ], StoreService); return StoreService; }()); var PageWrapperComponent = /** @class */ (function () { function PageWrapperComponent(dndService, storeService) { this.dndService = dndService; this.storeService = storeService; this.FormQLMode = FormQLMode; this.ContainerType = ContainerType; this.ComponentPositionType = GridPositionType; } PageWrapperComponent.prototype.ngOnInit = function () { this.sections = this.createSections(this.page); }; PageWrapperComponent.prototype.synchroniseModel = function ($event, positionId) { var dndEvent = { sourceObjectId: $event.sourceObjectId, sourceWrapperId: $event.sourceWrapperId, targetPositionId: positionId, targetWrapperId: this.page.pageId, targetIndexId: $event.targetIndexId }; this.page = this.dndService.synchronisePageModel(this.page, dndEvent); this.sections = this.createSections(this.page); this.storeService.reSetForm(InternalEventType.DndFormChanged, this.page); }; PageWrapperComponent.prototype.createSections = function (page) { var sections = {}; if (page && page.sections) page.sections.forEach(function (section) { if (sections && sections[section.position.id]) sections[section.position.id].push(section); else sections[section.position.id] = [section]; }); return sections; }; PageWrapperComponent.prototype.trackByFn = function (index, item) { return item.id; }; PageWrapperComponent.prototype.resetSections = function () { if (this.sections) this.sections = this.createSections(this.page); }; __decorate([ Input(), __metadata("design:type", Object) ], PageWrapperComponent.prototype, "page", void 0); __decorate([ Input(), __metadata("design:type", FormGroup) ], PageWrapperComponent.prototype, "reactivePage", void 0); __decorate([ Input(), __metadata("design:type", Number) ], PageWrapperComponent.prototype, "mode", void 0); PageWrapperComponent = __decorate([ Component({ // tslint:disable-next-line: component-selector selector: '[formql-page-wrapper]', template: "\n <div class=\"fql-page-body\">\n <ng-template formqlGdConfig\n [formqlGdConfigOf]=\"page.template.body\" let-bodyitem let-i=\"index\"\n (resetItems)=\"resetSections()\">\n <div\n [ngClass]=\"{'fql-page-container': mode === FormQLMode.Edit}\"\n [ngStyle]=\"bodyitem.style\">\n <div formqlDndDrop\n [type]=\"ContainerType.Section\"\n [mode]=\"mode\"\n [ngClass]=\"{'fql-page-container': (mode === FormQLMode.Edit)}\"\n (synchronise)=\"synchroniseModel($event, bodyitem.id)\">\n <ng-container *ngFor=\"let section of sections[bodyitem.id]; trackBy: trackByFn\">\n <ng-container *ngTemplateOutlet=\"templateRef; context: {section: section}\">\n </ng-container>\n </ng-container>\n </div>\n </div>\n </ng-template>\n </div>\n <ng-template #templateRef let-section=\"section\">\n <div [formGroup]=\"reactivePage\">\n <div formql-section-wrapper\n [page]=\"page\"\n [section]=\"section\"\n [formGroupName]=\"section.sectionId\"\n [reactiveSection]=\"reactivePage.controls[section.sectionId]\"\n [mode]=\"mode\">\n </div>\n </div>\n </ng-template>", providers: [DndService], styles: [".fql-bundle-field-input{width:100%;box-sizing:border-box;-webk