UNPKG

formgen-react

Version:

Formula generator with JSON for react. UI Fabric controls are used for rendering

507 lines 23.5 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || Object.assign || function(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; }; var __decorate = (this && this.__decorate) || function (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; }; Object.defineProperty(exports, "__esModule", { value: true }); require("core-js/es6/map"); require("core-js/es6/set"); var React = require("react"); var ObjectFabric_1 = require("../objects/ObjectFabric"); var Helper_1 = require("../Helper"); var Styling_1 = require("office-ui-fabric-react/lib/Styling"); var icons_1 = require("@uifabric/icons"); var JFormData_1 = require("../objects/JFormData"); var styling_1 = require("@uifabric/styling"); var PropTypes = require("prop-types"); var Utilities_1 = require("office-ui-fabric-react/lib/Utilities"); require("../styles/main.css"); var Enums_1 = require("../Enums"); var react_intl_1 = require("react-intl"); var Rendering_1 = require("./Rendering"); require("reflect-metadata"); var FormBaseInput_types_1 = require("../formBaseInput/FormBaseInput.types"); var TemplateHelper_1 = require("../objects/TemplateHelper"); global.Intl = require('intl'); var frLocaleData = require('react-intl/locale-data/fr'); var deLocaleData = require('react-intl/locale-data/de'); var enLocaleData = require('react-intl/locale-data/en'); var esLocaleData = require('react-intl/locale-data/es'); var itLocaleData = require('react-intl/locale-data/id'); react_intl_1.addLocaleData(frLocaleData); react_intl_1.addLocaleData(deLocaleData); react_intl_1.addLocaleData(enLocaleData); react_intl_1.addLocaleData(itLocaleData); react_intl_1.addLocaleData(esLocaleData); icons_1.initializeIcons(); exports.FormLanguage = ""; /** * The main Form Control that renders the Control Tree */ var GenericForm = /** @class */ (function (_super) { __extends(GenericForm, _super); /** * Load the correct langauge, UI Fabric theme and the rendering engine. */ function GenericForm(props) { var _this = _super.call(this, props) || this; if (_this.props.Language) { exports.FormLanguage = _this.props.Language; } _this._rendering = new Rendering_1.default(function () { return ObjectFabric_1.ObjectFabric.getJsonFromForm(_this.formData); }, props.customControls, props.customValidators, props.customActions, props.dataBinders, props.formInputs, props.onCancelForm); _this.formData = ObjectFabric_1.ObjectFabric.getForm(props.jsonFormData, props.formType ? props.formType : JFormData_1.JFormData); _this._mountedInputs = []; _this._controlEvents = []; _this._pristine = true; _this.state = { validationResults: {} }; _this._container = props.container; if (_this.formData.Theme) { Styling_1.loadTheme({ palette: { 'themePrimary': _this.formData.Theme } }); } return _this; } /** * Call the formDidMount event and take over the mounted controls */ GenericForm.prototype.componentDidMount = function () { var _loop_1 = function (eventControl) { var input = this_1._mountedInputs.find(function (c) { return c.props.inputKey == eventControl.senderControlKey; }); this_1._sendValutToControls(eventControl, input, true); }; var this_1 = this; for (var _i = 0, _a = this._controlEvents; _i < _a.length; _i++) { var eventControl = _a[_i]; _loop_1(eventControl); } if (this.props.formDidMount) { this.props.formDidMount(this._mountedInputs); } }; GenericForm.prototype.render = function () { var nativeProps = Utilities_1.getNativeProps(this.props, Utilities_1.divProperties); var internalFormTitle = this.props.showTemplateTitle ? TemplateHelper_1.TemplateHelper.getTemplatedTitle(this.props.jsonFormData) : undefined; if (!internalFormTitle) internalFormTitle = Helper_1.Helper.getTranslatedProperty(Enums_1.TranslatedProperty.Title, this.formData); return (React.createElement("form", __assign({}, nativeProps, { onSubmit: this._onSubmit, key: this.formData.ID }), React.createElement("div", { className: "Form", key: this.formData.ID + "div1" }, Enums_1.TranslatedProperty.Title && (React.createElement("header", { className: [ "Form-header", styling_1.FontClassNames.medium ].join(' '), key: this.formData.ID + "heder" }, React.createElement("h1", { key: this.formData.ID + "h1" }, this.props.formTitle ? this.props.formTitle : internalFormTitle))), React.createElement("div", { className: 'Form-content', key: this.formData.ID + "Container" }, this._rendering.buildRowWlements(this.formData.ID + "/R", this.formData.Rows))))); }; /** * Get the context for child components to use */ GenericForm.prototype.getChildContext = function () { return { isFormValid: this._isFormValid, mountInput: this._mountInput, unmountInput: this._unmountInput, submitValue: this._submitValue, formData: this.formData, container: this._container }; }; /** * Finde with the full control id the Control in the tree. * @param inputKey The full control id to finde the corresponding control */ GenericForm.prototype._findeControlFromKey = function (inputKey) { var control; var controlStruct = inputKey.split("."); if (this.formData.Rows) control = this._findeControlInRow(this.formData.Rows, controlStruct, 1); return control; }; /** * Validate an individual input and set its error state * Returns the validation result * @param input The input to validate * @param showValidation Set to true if the error message shoul be set */ GenericForm.prototype._validateComponent = function (input, showValidation) { if (!input.doValidate && input.props.validators) { var control = this._findeControlFromKey(input.props.inputKey); if (control && control.FormValidators.find(function (v) { return v.ValidatorType == Enums_1.ValidatorTypes.Required; })) { return { isValid: false, component: input, }; } } else if (input.doValidate) { var validationResult = input.doValidate(); if (showValidation && !validationResult.isValid) input.setError(validationResult.errorMessage); else if (!validationResult.isValid && (this.props.showErrorsWhenPristine || !this._pristine)) { input.setError(validationResult.errorMessage); } else { input.clearError(); } return validationResult; } return { isValid: true, component: input, }; }; /** * Validate all the individual inputs and set their error state * Returns a list of the validation results */ GenericForm.prototype._validateForm = function () { var _this = this; var validationResults = {}; this._mountedInputs.forEach(function (input) { validationResults[input.props.inputKey] = _this._validateComponent(input); }); this.setState(function (prevState) { prevState.validationResults = validationResults; return prevState; }); return validationResults; }; /** * When the form is submitted. This will validate the form and call the appropriate submit callback * @param event The form event */ GenericForm.prototype._onSubmit = function (event) { event.preventDefault(); if (this._pristine) { this._pristine = false; } var validationResults = this._validateForm(); var formIsValid = this._isFormValid(validationResults); var jsonData = ObjectFabric_1.ObjectFabric.getJsonFromForm(this.formData); if (formIsValid && this.props.onSubmitForm) { this.props.onSubmitForm(jsonData); } else if (this.props.onInvalidSubmitForm) { this.props.onInvalidSubmitForm(jsonData); } }; /** * Find the Control with the ID in the tree of controls * @param rows Row Array * @param controlStruct ID Structure. the Element 0 is the id from the form an will not be used * @param level The level in where to search in the contrlStruct. */ GenericForm.prototype._findeControlInRow = function (rows, controlStruct, level) { for (var _i = 0, rows_1 = rows; _i < rows_1.length; _i++) { var row = rows_1[_i]; for (var _a = 0, _b = row.Columns; _a < _b.length; _a++) { var col = _b[_a]; var control = this._findeControlInControls(col.Controls, controlStruct, level); if (control) return control; } } return undefined; }; /** * Find the Control with the ID in the tree of controls * @param controls Control Array * @param controlStruct ID Structure. the Element 0 is the id from the form an will not be used * @param level The level in where to search in the contrlStruct. */ GenericForm.prototype._findeControlInControls = function (controls, controlStruct, level) { var id = Helper_1.Helper.cleanUpKey(controlStruct[level]); var control = controls.find(function (c) { return c.ID == id; }); if (controlStruct.length - 1 != level) if (control && control.SubRows) control = this._findeControlInRow(control.SubRows, controlStruct, level + 1); else if (control && control.SubControls) control = this._findeControlInControls(control.SubControls, controlStruct, level + 1); return control; }; /** * Register an input with the form * @param input The input to register */ GenericForm.prototype._mountInput = function (input) { var _this = this; var foundControl = this._mountedInputs.find(function (g) { return g.props.inputKey == input.props.inputKey; }); if (foundControl == undefined) { if (!input.doValidate) this._mountedInputs.push(input); this.setState(function (prevState) { prevState.validationResults[input.props.inputKey] = _this._validateComponent(input); return prevState; }); } else if (input.doValidate && !foundControl.doValidate) { this._unmountInput(foundControl); this._mountInput(input); } var control = input.props.control; this._registerEvents(input, control.DataProviderDefaultValueConfigKey); this._registerEvents(input, control.DataProviderValueConfigKey); for (var _i = 0, _a = control.DataProviderConfigKeys; _i < _a.length; _i++) { var listProviderKey = _a[_i]; this._registerEvents(input, listProviderKey); } }; /** * Register if available the event on the control defined between squer brackets * @param input The input that has rais an update * @param key The key with square brackets */ GenericForm.prototype._registerEvents = function (input, key) { if (key) { var controlKey = Helper_1.Helper.getControlKeyFromConfigKey(key); if (controlKey) { this._registerEventInControlEvents(controlKey, input); } else if (!controlKey) { this._registerEventInControlEvents(input.props.inputKey, input); } else throw "Control definitions are maximal one allowed per key definition: " + key; } }; /** * Register the input in the controlEvents * @param controlKey The key from the control to register * @param input The input that has to register. */ GenericForm.prototype._registerEventInControlEvents = function (controlKey, input) { var eventType = this._controlEvents.find(function (c) { return c.senderControlKey == controlKey; }); var index = -1; if (eventType == undefined) { index = this._controlEvents.push({ senderControlKey: controlKey, receiverControl: [] }) - 1; } else { index = this._controlEvents.indexOf(eventType); } this._controlEvents[index].receiverControl.push(input); }; /** * Set the validation result, if Valid the control Value and if defined call the onUpdated Method * @param input The input that has rais an update * @param validate True if the input should validated. * @param skipSendValue True if the sendValutToControls should to be used (avoid recalling the event) */ GenericForm.prototype._submitValue = function (input, validate, skipSendValue) { var validationResult = this._validateComponent(input, validate); this.setState(function (prevState) { prevState.validationResults[input.props.inputKey] = validationResult; return prevState; }); console.log("sender:" + input.props.inputKey + ":" + validationResult.isValid); if (validationResult.isValid) { var control = this._findeControlFromKey(input.props.inputKey); if (control) { control.Value = input.state.currentValue; } var eventControl = this._controlEvents.find(function (c) { return c.senderControlKey == input.props.inputKey; }); if (eventControl && !skipSendValue) { this._sendValutToControls(eventControl, input); } if (this.props.onUpdated) { this.props.onUpdated(input.props.inputKey, input.state.currentValue); } } }; /** * Sed the senderControl Infos to the Receiver at the bound Control * @param eventControl The EventControl to get the receiver from * @param senderControl The sending controll * @param loadInitials If true then load also the controls that receiver and sender are the same control */ GenericForm.prototype._sendValutToControls = function (eventControl, senderControl, loadInitials) { for (var _i = 0, _a = eventControl.receiverControl; _i < _a.length; _i++) { var receiverControl = _a[_i]; if (!senderControl || receiverControl.props.inputKey == senderControl.props.inputKey) { if (loadInitials) { this._sendValutToControl(receiverControl, undefined); } } else { this._sendValutToControl(receiverControl, senderControl); } } }; /** * Send the value to an given control. If need convert it with the provider key to another value * @param input The input that has rais an update * @param value The value to be send */ GenericForm.prototype._sendValutToControl = function (receiverControl, senderControl) { var _this = this; for (var _i = 0, _a = receiverControl.props.control.DataProviderConfigKeys; _i < _a.length; _i++) { var providerKey = _a[_i]; var result = Helper_1.Helper.getControlKeyFromConfigKey(providerKey); if (result && senderControl) { receiverControl.setState({ currentFilter: senderControl.state.currentValue }); } } this._getValueFromProvider(receiverControl, senderControl, receiverControl.props.control.DataProviderValueConfigKey).then(function (valutToUse) { if (valutToUse && receiverControl.props.control.DataProviderValueConfigKey) { receiverControl.setValue(valutToUse, true, true); } if (receiverControl.props.control.DataProviderDefaultValueConfigKey && _this.props.isNewForm && !receiverControl.state.currentValue) { _this._getValueFromProvider(receiverControl, senderControl, receiverControl.props.control.DataProviderDefaultValueConfigKey).then(function (defaultValutToUse) { if (defaultValutToUse) receiverControl.setValue(defaultValutToUse, true, true); }); } }); }; /** * Get the value from a defined provider or default value. * @param input The input that has rais an update * @param value The value to be used when nothing others devined * @param keyToResolve The Key to resolve with the provider */ GenericForm.prototype._getValueFromProvider = function (receiverControl, senderControl, keyToResolve) { var _this = this; return new Promise(function (resolve, reject) { if ((!keyToResolve || keyToResolve == "") && senderControl) { resolve(senderControl.state.currentValue); return; } if ((!keyToResolve || keyToResolve == "") && !senderControl) { resolve(undefined); return; } var controlKey = Helper_1.Helper.getControlKeyFromConfigKey(keyToResolve); if (controlKey) keyToResolve = keyToResolve.replace(controlKey, controlKey.replace(".", "/")); var keyParts = keyToResolve.split("."); if (keyToResolve.startsWith("[") && keyParts.length == 1 && senderControl) { resolve(senderControl.state.currentValue); return; } if (keyToResolve.startsWith("[") && senderControl && senderControl.state.currentValue) { var objectToUse = senderControl.state.currentValue[keyParts[1]]; if (keyParts.length > 2) { for (var i = 2; i < keyParts.length; i++) { if (objectToUse != undefined) { objectToUse = objectToUse[keyParts[i]]; } } } resolve(objectToUse); return; } else { var providerKey_1 = keyParts[0]; var dataProviders = _this._container.get(FormBaseInput_types_1.typesForInject.IDataProviderCollection); if (dataProviders == undefined) throw "No DataProviders defined"; var provider = dataProviders.providers.find(function (p) { return p.providerServiceKey == providerKey_1; }); if (provider == undefined) throw "DataProvider with key " + providerKey_1 + " not found"; provider.formData = _this.formData; provider.initialize(); var providerConfigKey = Helper_1.Helper.getConfigKeyFromProviderKey(keyToResolve); var sender = senderControl ? senderControl.props.control : undefined; provider.retrieveSingleData(providerConfigKey, sender, receiverControl.props.control, Helper_1.Helper.getLanguage()).then(function (value) { resolve(value); }); } }); }; /** * Unregister an input with the form * @param input The input to unregister */ GenericForm.prototype._unmountInput = function (input) { var currentIndex = this._mountedInputs.indexOf(input); if (currentIndex > -1) { this._mountedInputs.splice(currentIndex, 1); this.setState(function (prevState) { delete prevState.validationResults[input.props.inputKey]; return prevState; }); } }; /** * Check if the form is valid. If all validations are ok then reutrn true. * @param validationResults All validation results from the control tree. */ GenericForm.prototype._isFormValid = function (validationResults) { if (validationResults === void 0) { validationResults = this.state.validationResults; } for (var key in validationResults) { if (!validationResults[key].isValid) { return false; } } return true; }; /** * This is needed because React 15's context does not work well with typescript */ GenericForm.childContextTypes = { isFormValid: PropTypes.func.isRequired, mountInput: PropTypes.func.isRequired, unmountInput: PropTypes.func.isRequired, submitValue: PropTypes.func.isRequired, formData: PropTypes.object.isRequired, container: PropTypes.object.isRequired }; __decorate([ Utilities_1.autobind ], GenericForm.prototype, "_onSubmit", null); __decorate([ Utilities_1.autobind ], GenericForm.prototype, "_mountInput", null); __decorate([ Utilities_1.autobind ], GenericForm.prototype, "_submitValue", null); __decorate([ Utilities_1.autobind ], GenericForm.prototype, "_unmountInput", null); __decorate([ Utilities_1.autobind ], GenericForm.prototype, "_isFormValid", null); return GenericForm; }(Utilities_1.BaseComponent)); exports.GenericForm = GenericForm; /** * Type alias for any simple form input */ var Form = /** @class */ (function (_super) { __extends(Form, _super); /** * Load basic form */ function Form(props) { return _super.call(this, props) || this; } return Form; }(GenericForm)); exports.Form = Form; //# sourceMappingURL=Form.js.map