UNPKG

@formql/core

Version:

FormQL - A framework for building dynamic forms

1,010 lines (988 loc) 132 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/forms'), require('@angular/common'), require('angular2-uuid'), require('rxjs'), require('rxjs/operators'), require('angular2-text-mask'), require('text-mask-addons')) : typeof define === 'function' && define.amd ? define('@formql/core', ['exports', '@angular/core', '@angular/forms', '@angular/common', 'angular2-uuid', 'rxjs', 'rxjs/operators', 'angular2-text-mask', 'text-mask-addons'], factory) : (global = global || self, factory((global.formql = global.formql || {}, global.formql.core = {}), global.ng.core, global.ng.forms, global.ng.common, global['angular2-uuid'], global.rxjs, global.rxjs.operators, global.angular2TextMask, global.textMaskAddons)); }(this, (function (exports, core, forms, common, angular2Uuid, rxjs, operators, angular2TextMask, textMaskAddons) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function __param(paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } } function __metadata(metadataKey, metadataValue) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spread() { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; } (function (ContainerType) { ContainerType[ContainerType["Section"] = 1] = "Section"; ContainerType[ContainerType["Component"] = 2] = "Component"; ContainerType[ContainerType["Page"] = 3] = "Page"; })(exports.ContainerType || (exports.ContainerType = {})); (function (FormQLMode) { FormQLMode[FormQLMode["View"] = 0] = "View"; FormQLMode[FormQLMode["Edit"] = 1] = "Edit"; })(exports.FormQLMode || (exports.FormQLMode = {})); var PlainLayoutComponent = /** @class */ (function () { function PlainLayoutComponent() { this.submit = new core.EventEmitter(); } PlainLayoutComponent.prototype.onSubmitTriggered = function () { this.submit.emit(null); }; PlainLayoutComponent.componentName = 'PlainLayoutComponent'; __decorate([ core.Input(), __metadata("design:type", Object) ], PlainLayoutComponent.prototype, "form", void 0); __decorate([ core.Input(), __metadata("design:type", forms.FormGroup) ], PlainLayoutComponent.prototype, "reactiveForm", void 0); __decorate([ core.Input(), __metadata("design:type", Number) ], PlainLayoutComponent.prototype, "mode", void 0); __decorate([ core.Output(), __metadata("design:type", Object) ], PlainLayoutComponent.prototype, "submit", void 0); PlainLayoutComponent = __decorate([ core.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: angular2Uuid.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: angular2Uuid.UUID.UUID(), label: 'New Component', componentName: 'FormQLLabelComponent', position: { id: '-1', index: 0 } }; }; DndService = __decorate([ core.Injectable() ], DndService); return DndService; }()); (function (GridPositionType) { GridPositionType[GridPositionType["Header"] = 1] = "Header"; GridPositionType[GridPositionType["Body"] = 2] = "Body"; GridPositionType[GridPositionType["Footer"] = 3] = "Footer"; })(exports.GridPositionType || (exports.GridPositionType = {})); (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"; })(exports.InternalEventType || (exports.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([ core.Injectable(), __metadata("design:paramtypes", [core.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 forms.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 forms.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 forms.FormGroup(componentGroup); }); pageGroup[page.pageId] = new forms.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 forms.FormControl) control.markAsTouched({ onlySelf: true }); else if (control instanceof forms.FormGroup) _this.validateForm(control); }); }; var HelperService_1; HelperService.ɵprov = core["ɵɵdefineInjectable"]({ factory: function HelperService_Factory() { return new HelperService(); }, token: HelperService, providedIn: "root" }); HelperService = HelperService_1 = __decorate([ core.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(operators.map(function (response) { return response; }), operators.concatMap(function (model) { return _this.injectedService.getData(model.dataSource, ids).pipe(operators.map(function (data) { return _this.initialiseFormState(model, data); })); })); else return this.injectedService.getForm(formName).pipe(operators.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(operators.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(operators.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(operators.map(function (data) { if (data) return data; else return {}; })); }; FormService.prototype.getForms = function () { return this.injectedService.getForms().pipe(operators.map(function (data) { return data; })); }; FormService.prototype.getForm = function (name) { return this.injectedService.getForm(name).pipe(operators.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 = core["ɵɵdefineInjectable"]({ factory: function FormService_Factory() { return new FormService(core["ɵɵinject"]("FormQLService"), core["ɵɵinject"](ComponentResolverService), core["ɵɵinject"](forms.FormBuilder)); }, token: FormService, providedIn: "root" }); FormService = __decorate([ core.Injectable({ providedIn: 'root' }), __param(0, core.Inject('FormQLService')), __metadata("design:paramtypes", [Object, ComponentResolverService, forms.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 rxjs.Subject(); this.formState$ = new rxjs.Subject(); this.serviceDestroyed = new rxjs.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(operators.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 exports.InternalEventType.EditingForm: this.populateReactiveForm(); break; case exports.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 exports.InternalEventType.RemoveComponent: v