UNPKG

@ohayojp/form

Version:
1,579 lines (1,566 loc) 266 kB
import { __rest, __decorate, __metadata } from 'tslib'; import { Platform } from '@angular/cdk/platform'; import { Injectable, Inject, ComponentFactoryResolver, EventEmitter, Component, ChangeDetectionStrategy, ViewEncapsulation, ChangeDetectorRef, Optional, Input, Output, ViewChild, ViewContainerRef, Directive, ElementRef, Renderer2, TemplateRef, Injector, HostBinding, NgModule } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import { ACLService } from '@ohayojp/acl'; import { OhayoLocaleService, OHAYO_I18N_TOKEN, OhayoLocaleModule } from '@ohayojp/theme'; import { toBoolean, deepCopy, OhayoConfigService, InputBoolean, InputNumber, toDate, deepGet, OhayoUtilModule } from '@ohayojp/util'; import { of, BehaviorSubject, Observable, combineLatest, Subject, merge } from 'rxjs'; import { map, distinctUntilChanged, takeUntil, filter, debounceTime, startWith, mergeMap, tap } from 'rxjs/operators'; import { CommonModule } from '@angular/common'; import { NgModel, FormsModule } from '@angular/forms'; import { NzAutocompleteModule } from 'ng-zorro-antd/auto-complete'; import { NzButtonModule } from 'ng-zorro-antd/button'; import { NzCardModule } from 'ng-zorro-antd/card'; import { NzCascaderModule } from 'ng-zorro-antd/cascader'; import { NzCheckboxModule } from 'ng-zorro-antd/checkbox'; import { NzDatePickerModule } from 'ng-zorro-antd/date-picker'; import { NzFormModule } from 'ng-zorro-antd/form'; import { NzGridModule } from 'ng-zorro-antd/grid'; import { NzIconModule } from 'ng-zorro-antd/icon'; import { NzInputModule } from 'ng-zorro-antd/input'; import { NzInputNumberModule } from 'ng-zorro-antd/input-number'; import { NzMentionModule } from 'ng-zorro-antd/mention'; import { NzModalService, NzModalModule } from 'ng-zorro-antd/modal'; import { NzRadioModule } from 'ng-zorro-antd/radio'; import { NzRateModule } from 'ng-zorro-antd/rate'; import { NzSelectModule } from 'ng-zorro-antd/select'; import { NzSliderModule } from 'ng-zorro-antd/slider'; import { NzSwitchModule } from 'ng-zorro-antd/switch'; import { NzTagModule } from 'ng-zorro-antd/tag'; import { NzTimePickerModule } from 'ng-zorro-antd/time-picker'; import { NzToolTipModule } from 'ng-zorro-antd/tooltip'; import { NzTransferModule } from 'ng-zorro-antd/transfer'; import { NzTreeSelectModule } from 'ng-zorro-antd/tree-select'; import { NzUploadModule } from 'ng-zorro-antd/upload'; import { helpMotion } from 'ng-zorro-antd/core/animation'; import format from 'date-fns/format'; /** * @fileoverview added by tsickle * Generated from: src/config.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const SF_DEFAULT_CONFIG = { formatMap: { 'date-time': { widget: 'date', showTime: true, format: `yyyy-MM-dd'T'HH:mm:ss.SSSxxx`, }, date: { widget: 'date', format: 'yyyy-MM-dd' }, 'full-date': { widget: 'date', format: 'yyyy-MM-dd' }, time: { widget: 'time', format: 'HH:mm:ss.SSSxxx' }, 'full-time': { widget: 'time' }, week: { widget: 'date', mode: 'week', format: 'yyyy-ww' }, month: { widget: 'date', mode: 'month', format: 'yyyy-MM' }, uri: { widget: 'upload' }, email: { widget: 'autocomplete', type: 'email' }, color: { widget: 'string', type: 'color' }, '': { widget: 'string' }, }, ingoreKeywords: ['type', 'enum'], liveValidate: true, autocomplete: null, firstVisual: false, onlyVisual: false, errors: {}, ui: (/** @type {?} */ ({})), button: (/** @type {?} */ ({ submit_type: 'primary', reset_type: 'default' })), uiDateStringFormat: 'yyyy-MM-dd HH:mm:ss', uiDateNumberFormat: 'T', uiTimeStringFormat: 'HH:mm:ss', uiTimeNumberFormat: 'T', uiEmailSuffixes: ['qq.com', '163.com', 'gmail.com', '126.com', 'aliyun.com'], }; /** * @param {?} srv * @return {?} */ function mergeConfig(srv) { return (/** @type {?} */ (srv.merge('sf', SF_DEFAULT_CONFIG))); } /** * @fileoverview added by tsickle * Generated from: src/const.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const SF_SEQ = '/'; /** * @fileoverview added by tsickle * Generated from: src/utils.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @param {?} o * @return {?} */ function isBlank(o) { return o == null; } /** * @param {?} value * @param {?} defaultValue * @return {?} */ function toBool(value, defaultValue) { value = toBoolean(value, true); return value == null ? defaultValue : value; } /** * @param {?} ui * @param {...?} args * @return {?} */ function di(ui, ...args) { if (ui.debug) { // tslint:disable-next-line:no-console console.warn(...args); } } /** * 根据 `$ref` 查找 `definitions` * @param {?} $ref * @param {?} definitions * @return {?} */ function findSchemaDefinition($ref, definitions) { /** @type {?} */ const match = /^#\/definitions\/(.*)$/.exec($ref); if (match && match[1]) { // parser JSON Pointer /** @type {?} */ const parts = match[1].split(SF_SEQ); /** @type {?} */ let current = definitions; for (let part of parts) { part = part.replace(/~1/g, SF_SEQ).replace(/~0/g, '~'); if (current.hasOwnProperty(part)) { current = current[part]; } else { throw new Error(`Could not find a definition for ${$ref}.`); } } return current; } throw new Error(`Could not find a definition for ${$ref}.`); } /** * 取回Schema,并处理 `$ref` 的关系 * @param {?} schema * @param {?=} definitions * @return {?} */ function retrieveSchema(schema, definitions = {}) { if (schema.hasOwnProperty('$ref')) { /** @type {?} */ const $refSchema = findSchemaDefinition((/** @type {?} */ (schema.$ref)), definitions); // remove $ref property const { $ref } = schema, localSchema = __rest(schema, ["$ref"]); return retrieveSchema(Object.assign(Object.assign({}, $refSchema), localSchema), definitions); } return schema; } /** * @param {?} _schema * @param {?} _ui * @return {?} */ function resolveIfSchema(_schema, _ui) { /** @type {?} */ const fn = (/** * @param {?} schema * @param {?} ui * @return {?} */ (schema, ui) => { resolveIf(schema, ui); Object.keys((/** @type {?} */ (schema.properties))).forEach((/** * @param {?} key * @return {?} */ key => { /** @type {?} */ const property = (/** @type {?} */ (schema.properties))[key]; /** @type {?} */ const uiKey = `$${key}`; if (property.items) { fn(property.items, ui[uiKey].$items); } if (property.properties) { fn(property, ui[uiKey]); } })); }); fn(_schema, _ui); } /** * @param {?} schema * @param {?} ui * @return {?} */ function resolveIf(schema, ui) { if (!(schema.hasOwnProperty('if') && schema.hasOwnProperty('then'))) return null; if (!(/** @type {?} */ (schema.if)).properties) throw new Error(`if: does not contain 'properties'`); /** @type {?} */ const allKeys = Object.keys((/** @type {?} */ (schema.properties))); /** @type {?} */ const ifKeys = Object.keys((/** @type {?} */ ((/** @type {?} */ (schema.if)).properties))); detectKey(allKeys, ifKeys); detectKey(allKeys, (/** @type {?} */ ((/** @type {?} */ (schema.then)).required))); schema.required = (/** @type {?} */ (schema.required)).concat((/** @type {?} */ ((/** @type {?} */ (schema.then)).required))); /** @type {?} */ const hasElse = schema.hasOwnProperty('else'); if (hasElse) { detectKey(allKeys, (/** @type {?} */ ((/** @type {?} */ (schema.else)).required))); schema.required = schema.required.concat((/** @type {?} */ ((/** @type {?} */ (schema.else)).required))); } /** @type {?} */ const visibleIf = {}; /** @type {?} */ const visibleElse = {}; ifKeys.forEach((/** * @param {?} key * @return {?} */ key => { /** @type {?} */ const cond = (/** @type {?} */ ((/** @type {?} */ (schema.if)).properties))[key].enum; visibleIf[key] = cond; if (hasElse) visibleElse[key] = (/** * @param {?} value * @return {?} */ (value) => !(/** @type {?} */ (cond)).includes(value)); })); (/** @type {?} */ ((/** @type {?} */ (schema.then)).required)).forEach((/** * @param {?} key * @return {?} */ key => (ui[`$${key}`].visibleIf = visibleIf))); if (hasElse) { (/** @type {?} */ ((/** @type {?} */ (schema.else)).required)).forEach((/** * @param {?} key * @return {?} */ key => (ui[`$${key}`].visibleIf = visibleElse))); } return schema; } /** * @param {?} keys * @param {?} detectKeys * @return {?} */ function detectKey(keys, detectKeys) { detectKeys.forEach((/** * @param {?} key * @return {?} */ key => { if (!keys.includes(key)) { throw new Error(`if: properties does not contain '${key}'`); } })); } /** * @param {?} properties * @param {?} order * @return {?} */ function orderProperties(properties, order) { if (!Array.isArray(order)) return properties; /** @type {?} */ const arrayToHash = (/** * @param {?} arr * @return {?} */ (arr) => arr.reduce((/** * @param {?} prev * @param {?} curr * @return {?} */ (prev, curr) => { prev[curr] = true; return prev; }), {})); /** @type {?} */ const errorPropList = (/** * @param {?} arr * @return {?} */ (arr) => `property [${arr.join(`', '`)}]`); /** @type {?} */ const propertyHash = arrayToHash(properties); /** @type {?} */ const orderHash = arrayToHash(order); /** @type {?} */ const extraneous = order.filter((/** * @param {?} prop * @return {?} */ prop => prop !== '*' && !propertyHash[prop])); if (extraneous.length) { throw new Error(`ui schema order list contains extraneous ${errorPropList(extraneous)}`); } /** @type {?} */ const rest = properties.filter((/** * @param {?} prop * @return {?} */ prop => !orderHash[prop])); /** @type {?} */ const restIndex = order.indexOf('*'); if (restIndex === -1) { if (rest.length) { throw new Error(`ui schema order list does not contain ${errorPropList(rest)}`); } return order; } if (restIndex !== order.lastIndexOf('*')) { throw new Error('ui schema order list contains more than one wildcard item'); } /** @type {?} */ const complete = [...order]; complete.splice(restIndex, 1, ...rest); return complete; } /** * @param {?} list * @param {?} formData * @param {?} readOnly * @return {?} */ function getEnum(list, formData, readOnly) { if (isBlank(list) || !Array.isArray(list) || list.length === 0) return []; if (typeof list[0] !== 'object') { list = list.map((/** * @param {?} item * @return {?} */ (item) => { return (/** @type {?} */ ({ label: item, value: item })); })); } if (formData) { if (!Array.isArray(formData)) formData = [formData]; list.forEach((/** * @param {?} item * @return {?} */ (item) => { if (~formData.indexOf(item.value)) item.checked = true; })); } // fix disabled status if (readOnly) { list.forEach((/** * @param {?} item * @return {?} */ (item) => (item.disabled = true))); } return list; } /** * @param {?} list * @param {?} formData * @param {?} readOnly * @return {?} */ function getCopyEnum(list, formData, readOnly) { return getEnum(deepCopy(list || []), formData, readOnly); } /** * @param {?} schema * @param {?} ui * @param {?} formData * @param {?=} asyncArgs * @return {?} */ function getData(schema, ui, formData, asyncArgs) { if (typeof ui.asyncData === 'function') { return ui.asyncData(asyncArgs).pipe(map((/** * @param {?} list * @return {?} */ (list) => getEnum(list, formData, (/** @type {?} */ (schema.readOnly)))))); } return of(getCopyEnum((/** @type {?} */ (schema.enum)), formData, (/** @type {?} */ (schema.readOnly)))); } /** * Whether to using date-fns to format a date * @param {?} srv * @return {?} */ function isDateFns(srv) { if (!srv) return false; /** @type {?} */ const data = srv.getDateLocale(); // Compatible date-fns v1.x & v2.x return data != null && !!data.formatDistance; // (!!data.distanceInWords || !!data.formatDistance); } /** * @fileoverview added by tsickle * Generated from: src/model/form.property.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @abstract */ class FormProperty { /** * @param {?} schemaValidatorFactory * @param {?} schema * @param {?} ui * @param {?} formData * @param {?} parent * @param {?} path * @param {?} _options */ constructor(schemaValidatorFactory, schema, ui, formData, parent, path, _options) { this._options = _options; this._errors = null; this._valueChanges = new BehaviorSubject({ path: null, pathValue: null, value: null }); this._errorsChanges = new BehaviorSubject(null); this._visible = true; this._visibilityChanges = new BehaviorSubject(true); this._objErrors = {}; this._value = null; this.schema = schema; this.ui = ui; this.schemaValidator = schemaValidatorFactory.createValidatorFn(schema, { ingoreKeywords: (/** @type {?} */ (this.ui.ingoreKeywords)), debug: (/** @type {?} */ ((/** @type {?} */ (((/** @type {?} */ (ui))))).debug)), }); this.formData = formData || schema.default; this._parent = parent; if (parent) { this._root = parent.root; } else { this._root = (/** @type {?} */ (this)); } this.path = path; } /** * @return {?} */ get valueChanges() { return this._valueChanges; } /** * @return {?} */ get errorsChanges() { return this._errorsChanges; } /** * @return {?} */ get type() { return (/** @type {?} */ (this.schema.type)); } /** * @return {?} */ get parent() { return this._parent; } /** * @return {?} */ get root() { return this._root; } /** * @return {?} */ get value() { return this._value; } /** * @return {?} */ get errors() { return this._errors; } /** * @return {?} */ get visible() { return this._visible; } /** * @return {?} */ get valid() { return this._errors === null || this._errors.length === 0; } /** * @return {?} */ get options() { return this._options; } /** * 更新值且校验数据 * @param {?=} options * @return {?} */ updateValueAndValidity(options) { options = Object.assign({ onlySelf: false, emitValidator: true, emitValueEvent: true, updatePath: '', updateValue: null }, options); this._updateValue(); if (options.emitValueEvent) { options.updatePath = options.updatePath || this.path; options.updateValue = options.updateValue || this.value; this.valueChanges.next({ value: this.value, path: options.updatePath, pathValue: options.updateValue }); } // `emitValidator` 每一次数据变更已经包含完整错误链路,后续父节点数据变更无须再触发校验 if (options.emitValidator && this.ui.liveValidate === true) { this._runValidation(); } if (this.parent && !options.onlySelf) { this.parent.updateValueAndValidity(Object.assign(Object.assign({}, options), { emitValidator: false })); } } /** * 根据路径搜索表单属性 * @param {?} path * @return {?} */ searchProperty(path) { /** @type {?} */ let prop = this; /** @type {?} */ let base = null; /** @type {?} */ let result = null; if (path[0] === SF_SEQ) { base = this.findRoot(); result = base.getProperty(path.substr(1)); } else { while (result === null && prop.parent !== null) { prop = base = prop.parent; result = base.getProperty(path); } } return (/** @type {?} */ (result)); } /** * 查找根表单属性 * @return {?} */ findRoot() { /** @type {?} */ let property = this; while (property.parent !== null) { property = property.parent; } return (/** @type {?} */ (property)); } // #region process errors /** * @private * @param {?} value * @return {?} */ isEmptyData(value) { if (isBlank(value)) return true; switch (this.type) { case 'string': return ('' + value).length === 0; } return false; } /** * \@internal * @return {?} */ _runValidation() { /** @type {?} */ let errors; // The definition of some rules: // 1. Should not ajv validator when is empty data and required fields // 2. Should not ajv validator when is empty data /** @type {?} */ const isEmpty = this.isEmptyData(this._value); if (isEmpty && this.ui._required) { errors = [{ keyword: 'required' }]; } else if (isEmpty) { errors = []; } else { errors = this.schemaValidator(this._value) || []; } /** @type {?} */ const customValidator = ((/** @type {?} */ (this.ui))).validator; if (typeof customValidator === 'function') { /** @type {?} */ const customErrors = customValidator(this.value, this, this.findRoot()); if (customErrors instanceof Observable) { customErrors.subscribe((/** * @param {?} res * @return {?} */ res => { this.setCustomErrors(errors, res); this.widget.detectChanges(); })); return; } this.setCustomErrors(errors, customErrors); return; } this._errors = errors; this.setErrors(this._errors); } /** * @private * @param {?} errors * @param {?} list * @return {?} */ setCustomErrors(errors, list) { // fix error format /** @type {?} */ const hasCustomError = list != null && list.length > 0; if (hasCustomError) { list.forEach((/** * @param {?} err * @return {?} */ err => { if (!err.message) { throw new Error(`The custom validator must contain a 'message' attribute to viewed error text`); } err._custom = true; })); } this._errors = this.mergeErrors(errors, list); this.setErrors(this._errors); } /** * @private * @param {?} errors * @param {?} newErrors * @return {?} */ mergeErrors(errors, newErrors) { if (newErrors) { if (Array.isArray(newErrors)) { errors = errors.concat(...newErrors); } else { errors.push(newErrors); } } return errors; } /** * @protected * @param {?} errors * @param {?=} emitFormat * @return {?} */ setErrors(errors, emitFormat = true) { if (emitFormat && errors && !this.ui.onlyVisual) { /** @type {?} */ const l = (this.widget && this.widget.l.error) || {}; errors = errors.map((/** * @param {?} err * @return {?} */ (err) => { /** @type {?} */ let message = err._custom === true && err.message ? err.message : (this.ui.errors || {})[err.keyword] || (/** @type {?} */ (this._options.errors))[err.keyword] || l[err.keyword] || ``; if (message && typeof message === 'function') { message = (/** @type {?} */ (message(err))); } if (message) { if (~((/** @type {?} */ (message))).indexOf('{')) { message = ((/** @type {?} */ (message))).replace(/{([\.a-z0-9]+)}/g, (/** * @param {?} _v * @param {?} key * @return {?} */ (_v, key) => (/** @type {?} */ (err.params))[key] || '')); } err.message = (/** @type {?} */ (message)); } return err; })); } this._errors = errors; this._errorsChanges.next(errors); // Should send errors to parent field if (this._parent) { this._parent.setParentAndPlatErrors(errors, this.path); } } /** * @param {?} errors * @param {?} path * @return {?} */ setParentAndPlatErrors(errors, path) { this._objErrors[path] = errors; /** @type {?} */ const platErrors = []; Object.keys(this._objErrors).forEach((/** * @param {?} p * @return {?} */ p => { /** @type {?} */ const property = this.searchProperty(p); if (property && !property.visible) return; platErrors.push(...this._objErrors[p]); })); this.setErrors(platErrors, false); } // #endregion // #region condition /** * @private * @param {?} visible * @return {?} */ setVisible(visible) { var _a, _b; this._visible = visible; this._visibilityChanges.next(visible); // 部分数据源来自 reset if (((_b = (_a = this.root.widget) === null || _a === void 0 ? void 0 : _a.sfComp) === null || _b === void 0 ? void 0 : _b._inited) === true) { this.resetValue(this.value, true); } } // A field is visible if AT LEAST ONE of the properties it depends on is visible AND has a value in the list /** * @return {?} */ _bindVisibility() { /** @type {?} */ const visibleIf = ((/** @type {?} */ (this.ui))).visibleIf; if (typeof visibleIf === 'object' && Object.keys(visibleIf).length === 0) { this.setVisible(false); } else if (visibleIf !== undefined) { /** @type {?} */ const propertiesBinding = []; for (const dependencyPath in visibleIf) { if (visibleIf.hasOwnProperty(dependencyPath)) { /** @type {?} */ const property = this.searchProperty(dependencyPath); if (property) { /** @type {?} */ const valueCheck = property.valueChanges.pipe(map((/** * @param {?} res * @return {?} */ res => { /** @type {?} */ const vi = visibleIf[dependencyPath]; if (typeof vi === 'function') { return vi(res.value); } if (vi.indexOf('$ANY$') !== -1) { return res.value.length > 0; } else { return vi.indexOf(res.value) !== -1; } }))); /** @type {?} */ const visibilityCheck = property._visibilityChanges; /** @type {?} */ const and = combineLatest([valueCheck, visibilityCheck]).pipe(map((/** * @param {?} results * @return {?} */ results => results[0] && results[1]))); propertiesBinding.push(and); } else { console.warn(`Can't find property ${dependencyPath} for visibility check of ${this.path}`); } } } combineLatest(propertiesBinding) .pipe(map((/** * @param {?} values * @return {?} */ values => values.indexOf(true) !== -1)), distinctUntilChanged()) .subscribe((/** * @param {?} visible * @return {?} */ visible => this.setVisible(visible))); } } } if (false) { /** * @type {?} * @private */ FormProperty.prototype._errors; /** * @type {?} * @private */ FormProperty.prototype._valueChanges; /** * @type {?} * @private */ FormProperty.prototype._errorsChanges; /** * @type {?} * @private */ FormProperty.prototype._visible; /** * @type {?} * @private */ FormProperty.prototype._visibilityChanges; /** * @type {?} * @private */ FormProperty.prototype._root; /** * @type {?} * @private */ FormProperty.prototype._parent; /** @type {?} */ FormProperty.prototype._objErrors; /** @type {?} */ FormProperty.prototype.schemaValidator; /** @type {?} */ FormProperty.prototype.schema; /** @type {?} */ FormProperty.prototype.ui; /** @type {?} */ FormProperty.prototype.formData; /** @type {?} */ FormProperty.prototype._value; /** @type {?} */ FormProperty.prototype.widget; /** @type {?} */ FormProperty.prototype.path; /** * @type {?} * @private */ FormProperty.prototype._options; /** * 设置值 * * @abstract * @param {?} value * @param {?} onlySelf `true` 只对当前字段更新值和校验;`false` 包含上级字段 * @return {?} */ FormProperty.prototype.setValue = function (value, onlySelf) { }; /** * 重置值,默认值为 `schema.default` * * @abstract * @param {?} value * @param {?} onlySelf `true` 只对当前字段更新值和校验;`false` 包含上级字段 * @return {?} */ FormProperty.prototype.resetValue = function (value, onlySelf) { }; /** * \@internal * @abstract * @return {?} */ FormProperty.prototype._hasValue = function () { }; /** * \@internal * @abstract * @return {?} */ FormProperty.prototype._updateValue = function () { }; } /** * @abstract */ class PropertyGroup extends FormProperty { constructor() { super(...arguments); this.properties = null; } /** * @param {?} path * @return {?} */ getProperty(path) { /** @type {?} */ const subPathIdx = path.indexOf(SF_SEQ); /** @type {?} */ const propertyId = subPathIdx !== -1 ? path.substr(0, subPathIdx) : path; /** @type {?} */ let property = ((/** @type {?} */ (this.properties)))[propertyId]; if (property !== null && subPathIdx !== -1 && property instanceof PropertyGroup) { /** @type {?} */ const subPath = path.substr(subPathIdx + 1); property = (/** @type {?} */ (((/** @type {?} */ (property))).getProperty(subPath))); } return property; } /** * @param {?} fn * @return {?} */ forEachChild(fn) { for (const propertyId in this.properties) { if (this.properties.hasOwnProperty(propertyId)) { /** @type {?} */ const property = ((/** @type {?} */ (this.properties)))[propertyId]; fn(property, propertyId); } } } /** * @param {?} fn * @return {?} */ forEachChildRecursive(fn) { this.forEachChild((/** * @param {?} child * @return {?} */ child => { fn(child); if (child instanceof PropertyGroup) { ((/** @type {?} */ (child))).forEachChildRecursive(fn); } })); } /** * @return {?} */ _bindVisibility() { super._bindVisibility(); this._bindVisibilityRecursive(); } /** * @private * @return {?} */ _bindVisibilityRecursive() { this.forEachChildRecursive((/** * @param {?} property * @return {?} */ property => { property._bindVisibility(); })); } /** * @return {?} */ isRoot() { return this === this.root; } } if (false) { /** @type {?} */ PropertyGroup.prototype.properties; } /** * @fileoverview added by tsickle * Generated from: src/model/object.property.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class ObjectProperty extends PropertyGroup { /** * @param {?} formPropertyFactory * @param {?} schemaValidatorFactory * @param {?} schema * @param {?} ui * @param {?} formData * @param {?} parent * @param {?} path * @param {?} options */ constructor(formPropertyFactory, schemaValidatorFactory, schema, ui, formData, parent, path, options) { super(schemaValidatorFactory, schema, ui, formData, parent, path, options); this.formPropertyFactory = formPropertyFactory; this._propertiesId = []; this.createProperties(); } /** * @return {?} */ get propertiesId() { return this._propertiesId; } /** * @private * @return {?} */ createProperties() { this.properties = {}; this._propertiesId = []; /** @type {?} */ let orderedProperties; try { orderedProperties = orderProperties(Object.keys((/** @type {?} */ (this.schema.properties))), (/** @type {?} */ (this.ui.order))); } catch (e) { console.error(`Invalid ${this.schema.title || 'root'} object field configuration:`, e); } (/** @type {?} */ (orderedProperties)).forEach((/** * @param {?} propertyId * @return {?} */ propertyId => { ((/** @type {?} */ (this.properties)))[propertyId] = this.formPropertyFactory.createProperty((/** @type {?} */ (this.schema.properties))[propertyId], this.ui['$' + propertyId], ((/** @type {?} */ ((this.formData || {}))))[propertyId], this, propertyId); this._propertiesId.push(propertyId); })); } /** * @param {?} value * @param {?} onlySelf * @return {?} */ setValue(value, onlySelf) { /** @type {?} */ const properties = (/** @type {?} */ (this.properties)); for (const propertyId in value) { if (value.hasOwnProperty(propertyId) && properties[propertyId]) { ((/** @type {?} */ (properties[propertyId]))).setValue(value[propertyId], true); } } this.updateValueAndValidity({ onlySelf, emitValueEvent: true }); } /** * @param {?} value * @param {?} onlySelf * @return {?} */ resetValue(value, onlySelf) { value = value || this.schema.default || {}; /** @type {?} */ const properties = (/** @type {?} */ (this.properties)); // tslint:disable-next-line: forin for (const propertyId in this.schema.properties) { properties[propertyId].resetValue(value[propertyId], true); } this.updateValueAndValidity({ onlySelf, emitValueEvent: true }); } /** * @return {?} */ _hasValue() { return this.value != null && !!Object.keys(this.value).length; } /** * @return {?} */ _updateValue() { /** @type {?} */ const value = {}; this.forEachChild((/** * @param {?} property * @param {?} propertyId * @return {?} */ (property, propertyId) => { if (property.visible && property._hasValue()) { value[propertyId] = property.value; } })); this._value = value; } } if (false) { /** * @type {?} * @private */ ObjectProperty.prototype._propertiesId; /** * @type {?} * @private */ ObjectProperty.prototype.formPropertyFactory; } /** * @fileoverview added by tsickle * Generated from: src/model/array.property.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class ArrayProperty extends PropertyGroup { /** * @param {?} formPropertyFactory * @param {?} schemaValidatorFactory * @param {?} schema * @param {?} ui * @param {?} formData * @param {?} parent * @param {?} path * @param {?} options */ constructor(formPropertyFactory, schemaValidatorFactory, schema, ui, formData, parent, path, options) { super(schemaValidatorFactory, schema, ui, formData, parent, path, options); this.formPropertyFactory = formPropertyFactory; this.properties = []; } /** * @param {?} path * @return {?} */ getProperty(path) { /** @type {?} */ const subPathIdx = path.indexOf(SF_SEQ); /** @type {?} */ const pos = +(subPathIdx !== -1 ? path.substr(0, subPathIdx) : path); /** @type {?} */ const list = (/** @type {?} */ (this.properties)); if (isNaN(pos) || pos >= list.length) { return undefined; } /** @type {?} */ const subPath = path.substr(subPathIdx + 1); return list[pos].getProperty(subPath); } /** * @param {?} value * @param {?} onlySelf * @return {?} */ setValue(value, onlySelf) { this.properties = []; this.clearErrors(); this.resetProperties(value); this.updateValueAndValidity({ onlySelf, emitValueEvent: true }); } /** * @param {?} value * @param {?} onlySelf * @return {?} */ resetValue(value, onlySelf) { this._value = value || this.schema.default || []; this.setValue(this._value, onlySelf); } /** * @return {?} */ _hasValue() { return true; } /** * @return {?} */ _updateValue() { /** @type {?} */ const value = []; this.forEachChild((/** * @param {?} property * @return {?} */ (property) => { var _a; if (property.visible && property._hasValue()) { value.push(Object.assign(Object.assign({}, (((_a = this.widget) === null || _a === void 0 ? void 0 : _a.cleanValue) ? null : property.formData)), property.value)); } })); this._value = value; } /** * @private * @param {?} formData * @return {?} */ addProperty(formData) { /** @type {?} */ const newProperty = (/** @type {?} */ (this.formPropertyFactory.createProperty((/** @type {?} */ (this.schema.items)), this.ui.$items, formData, (/** @type {?} */ (this))))); ((/** @type {?} */ (this.properties))).push(newProperty); return newProperty; } /** * @private * @param {?} formDatas * @return {?} */ resetProperties(formDatas) { for (const item of formDatas) { /** @type {?} */ const property = this.addProperty(item); property.resetValue(item, true); } } /** * @private * @param {?=} property * @return {?} */ clearErrors(property) { (property || this)._objErrors = {}; } // #region actions /** * @param {?} formData * @return {?} */ add(formData) { /** @type {?} */ const newProperty = this.addProperty(formData); newProperty.resetValue(formData, false); return newProperty; } /** * @param {?} index * @return {?} */ remove(index) { /** @type {?} */ const list = (/** @type {?} */ (this.properties)); this.clearErrors(); list.splice(index, 1); list.forEach((/** * @param {?} property * @param {?} idx * @return {?} */ (property, idx) => { property.path = [(/** @type {?} */ (property.parent)).path, idx].join(SF_SEQ); this.clearErrors(property); // TODO: 受限于 sf 的设计思路,对于移除数组项需要重新对每个子项进行校验,防止错误被父级合并后引起始终是错误的现象 if (property instanceof ObjectProperty) { property.forEachChild((/** * @param {?} p * @return {?} */ p => { p.updateValueAndValidity(); })); } })); if (list.length === 0) { this.updateValueAndValidity(); } } } if (false) { /** * @type {?} * @private */ ArrayProperty.prototype.formPropertyFactory; } /** * @fileoverview added by tsickle * Generated from: src/model/atomic.property.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @abstract */ class AtomicProperty extends FormProperty { /** * @param {?} value * @param {?} onlySelf * @return {?} */ setValue(value, onlySelf) { this._value = value; this.updateValueAndValidity({ onlySelf, emitValueEvent: true }); } /** * @param {?} value * @param {?} onlySelf * @return {?} */ resetValue(value, onlySelf) { if (value == null) { value = this.schema.default !== undefined ? this.schema.default : this.fallbackValue(); } this._value = value; this.updateValueAndValidity({ onlySelf, emitValueEvent: true }); if (this.widget) this.widget.reset(value); } /** * @return {?} */ _hasValue() { return this.fallbackValue() !== this.value; } /** * @return {?} */ _updateValue() { } } if (false) { /** * @abstract * @return {?} */ AtomicProperty.prototype.fallbackValue = function () { }; } /** * @fileoverview added by tsickle * Generated from: src/model/boolean.property.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class BooleanProperty extends AtomicProperty { /** * @return {?} */ fallbackValue() { return null; } } /** * @fileoverview added by tsickle * Generated from: src/model/number.property.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class NumberProperty extends AtomicProperty { /** * @return {?} */ fallbackValue() { return null; } /** * @param {?} value * @param {?} onlySelf * @return {?} */ setValue(value, onlySelf) { if (typeof value === 'string') { if (value.length) { value = value.indexOf('.') > -1 ? parseFloat(value) : parseInt(value, 10); } else { value = undefined; } } this._value = value; this.updateValueAndValidity({ onlySelf, emitValueEvent: true }); } } /** * @fileoverview added by tsickle * Generated from: src/model/string.property.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class StringProperty extends AtomicProperty { /** * @return {?} */ fallbackValue() { return null; } /** * @param {?} value * @param {?} onlySelf * @return {?} */ setValue(value, onlySelf) { this._value = value == null ? '' : value; this.updateValueAndValidity({ onlySelf, emitValueEvent: true }); } } /** * @fileoverview added by tsickle * Generated from: src/model/form.property.factory.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class FormPropertyFactory { /** * @param {?} schemaValidatorFactory * @param {?} cogSrv */ constructor(schemaValidatorFactory, cogSrv) { this.schemaValidatorFactory = schemaValidatorFactory; this.options = mergeConfig(cogSrv); } /** * @param {?} schema * @param {?} ui * @param {?} formData * @param {?=} parent * @param {?=} propertyId * @return {?} */ createProperty(schema, ui, formData, parent = null, propertyId) { /** @type {?} */ let newProperty = null; /** @type {?} */ let path = ''; if (parent) { path += parent.path; if (parent.parent !== null) { path += SF_SEQ; } switch (parent.type) { case 'object': path += propertyId; break; case 'array': path += ((/** @type {?} */ (((/** @type {?} */ (parent))).properties))).length; break; default: throw new Error('Instanciation of a FormProperty with an unknown parent type: ' + parent.type); } } else { path = SF_SEQ; } if (schema.$ref) { /** @type {?} */ const refSchema = retrieveSchema(schema, (/** @type {?} */ (parent)).root.schema.definitions); newProperty = this.createProperty(refSchema, ui, formData, parent, path); } else { // fix required if ((propertyId && (/** @type {?} */ ((/** @type {?} */ (parent)).schema.required)).indexOf((/** @type {?} */ (propertyId.split(SF_SEQ).pop()))) !== -1) || ui.showRequired === true) { ui._required = true; } // fix title if (schema.title == null) { schema.title = propertyId; } // fix date if ((schema.type === 'string' || schema.type === 'number') && !schema.format && !((/** @type {?} */ (ui))).format) { if (((/** @type {?} */ (ui))).widget === 'date') ui._format = schema.type === 'string' ? this.options.uiDateStringFormat : this.options.uiDateNumberFormat; else if (((/** @type {?} */ (ui))).widget === 'time') ui._format = schema.type === 'string' ? this.options.uiTimeStringFormat : this.options.uiTimeNumberFormat; } else { ui._format = ui.format; } switch (schema.type) { case 'integer': case 'number': newProperty = new NumberProperty(this.schemaValidatorFactory, schema, ui, formData, parent, path, this.options); break; case 'string': newProperty = new StringProperty(this.schemaValidatorFactory, schema, ui, formData, parent, path, this.options); break; case 'boolean': newProperty = new BooleanProperty(this.schemaValidatorFactory, schema, ui, formData, parent, path, this.options); break; case 'object': newProperty = new ObjectProperty(this, this.schemaValidatorFactory, schema, ui, formData, parent, path, this.options); break; case 'array': newProperty = new ArrayProperty(this, this.schemaValidatorFactory, schema, ui, formData, parent, path, this.options); break; default: throw new TypeError(`Undefined type ${schema.type}`); } } if (newProperty instanceof PropertyGroup) { this.initializeRoot(newProperty); } return newProperty; } /** * @private * @param {?} rootProperty * @return {?} */ initializeRoot(rootProperty) { // rootProperty.init(); rootProperty._bindVisibility(); } } if (false) { /** * @type {?} * @private */ FormPropertyFactory.prototype.options; /** * @type {?} * @private */ FormPropertyFactory.prototype.schemaValidatorFactory; } /** * @fileoverview added by tsickle * Generated from: src/terminator.service.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class TerminatorService { constructor() { this.onDestroy = new Subject(); } /** * @return {?} */ destroy() { this.onDestroy.next(true); } } if (false) { /** @type {?} */ TerminatorService.prototype.onDestroy; } /** * @fileoverview added by tsickle * Generated from: src/validator.factory.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @abstract */ class SchemaValidatorFactory { } SchemaValidatorFactory.decorators = [ { type: Injectable } ]; if (false) { /** * @abstract * @param {?} schema * @param {?} extraOptions * @return {?} */ SchemaValidatorFactory.prototype.createValidatorFn = function (schema, extraOptions) { }; } class AjvSchemaValidatorFactory extends SchemaValidatorFactory { /** * @param {?} cogSrv */ constructor(cogSrv) { super(); if (!(typeof document === 'object' && !!document)) { return; } this.options = mergeConfig(cogSrv); this.ajv = new Ajv(Object.assign(Object.assign({}, this.options.ajv), { errorDataPath: 'property', allErrors: true, jsonPointers: true })); this.ajv.addFormat('data-url', /^data:([a-z]+\/[a-z0-9-+.]+)?;name=(.*);base64,(.*)$/); this.ajv.addFormat('color', /^(#?([0-9A-Fa-f]{3}){1,2}\b|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/); this.ajv.addFormat('mobile', /^(0|\+?86|17951)?1[0-9]{10}$/); this.ajv.addFormat('id-card', /(^\d{15}$)|(^\d{17}([0-9]|X