devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
1,156 lines (1,153 loc) • 62.3 kB
JavaScript
/**
* DevExtreme (cjs/__internal/ui/form/form.js)
* Version: 25.2.3
* Build date: Fri Dec 12 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
require("../../../ui/validation_summary");
require("../../../ui/validation_group");
var _events_engine = _interopRequireDefault(require("../../../common/core/events/core/events_engine"));
var _visibility_change = require("../../../common/core/events/visibility_change");
var _message = _interopRequireDefault(require("../../../common/core/localization/message"));
var _component_registrator = _interopRequireDefault(require("../../../core/component_registrator"));
var _config = _interopRequireDefault(require("../../../core/config"));
var _element = require("../../../core/element");
var _guid = _interopRequireDefault(require("../../../core/guid"));
var _renderer = _interopRequireDefault(require("../../../core/renderer"));
var _resize_observer = _interopRequireDefault(require("../../../core/resize_observer"));
var _common = require("../../../core/utils/common");
var _deferred = require("../../../core/utils/deferred");
var _extend = require("../../../core/utils/extend");
var _iterator = require("../../../core/utils/iterator");
var _type = require("../../../core/utils/type");
var _window = require("../../../core/utils/window");
var _themes = require("../../../ui/themes");
var _ui = _interopRequireDefault(require("../../../ui/widget/ui.errors"));
var _conditional_invoke = require("../../core/utils/conditional_invoke");
var _m_console = require("../../core/utils/m_console");
var _widget = _interopRequireWildcard(require("../../core/widget/widget"));
var _m_drop_down_editor = require("../../ui/drop_down_editor/m_drop_down_editor");
var _editor = _interopRequireDefault(require("../../ui/editor/editor"));
var _label = require("../../ui/form/components/label");
var _constants = require("../../ui/form/constants");
var _formAi = require("../../ui/form/form.ai.utils");
var _form = _interopRequireDefault(require("../../ui/form/form.item_options_actions"));
var _form2 = _interopRequireDefault(require("../../ui/form/form.items_runtime_info"));
var _form3 = _interopRequireDefault(require("../../ui/form/form.layout_manager"));
var _form4 = require("../../ui/form/form.load_panel");
var _form5 = require("../../ui/form/form.utils");
var _load_panel = _interopRequireDefault(require("../../ui/load_panel"));
var _m_validation_engine = _interopRequireDefault(require("../../ui/m_validation_engine"));
var _m_validation_summary = _interopRequireDefault(require("../../ui/m_validation_summary"));
var _scrollable = _interopRequireDefault(require("../../ui/scroll_view/scrollable"));
var _tab_panel = _interopRequireDefault(require("../../ui/tab_panel/tab_panel"));
var _m_text_editor = require("../../ui/text_box/m_text_editor.base");
var _constants2 = require("../../ui/toolbar/constants");
function _getRequireWildcardCache(e) {
if ("function" != typeof WeakMap) {
return null
}
var r = new WeakMap,
t = new WeakMap;
return (_getRequireWildcardCache = function(e) {
return e ? t : r
})(e)
}
function _interopRequireWildcard(e, r) {
if (!r && e && e.__esModule) {
return e
}
if (null === e || "object" != typeof e && "function" != typeof e) {
return {
default: e
}
}
var t = _getRequireWildcardCache(r);
if (t && t.has(e)) {
return t.get(e)
}
var n = {
__proto__: null
},
a = Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var u in e) {
if ("default" !== u && {}.hasOwnProperty.call(e, u)) {
var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;
i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]
}
}
return n.default = e, t && t.set(e, n), n
}
function _interopRequireDefault(e) {
return e && e.__esModule ? e : {
default: e
}
}
const ITEM_OPTIONS_FOR_VALIDATION_UPDATING = ["items", "isRequired", "validationRules", "visible"];
class Form extends _widget.default {
constructor() {
super(...arguments);
this._currentAICommand = void 0
}
_init() {
super._init();
this._dirtyFields = new Set;
this._cachedColCountOptions = [];
this._itemsRunTimeInfo = new _form2.default;
this._groupsColCount = [];
this._attachSyncSubscriptions();
this._createSmartPastingAction();
this._createSmartPastedAction()
}
_getDefaultOptions() {
return Object.assign({}, super._getDefaultOptions(), {
formID: `dx-${new _guid.default}`,
formData: {},
colCount: 1,
screenByWidth: _window.defaultScreenFactorFunc,
labelLocation: "left",
readOnly: false,
onFieldDataChanged: null,
customizeItem: null,
onEditorEnterKey: null,
minColWidth: 200,
alignItemLabels: true,
alignItemLabelsInAllGroups: true,
alignRootItemLabels: true,
showColonAfterLabel: true,
showRequiredMark: true,
showOptionalMark: false,
requiredMark: "*",
optionalMark: _message.default.format("dxForm-optionalMark"),
requiredMessage: _message.default.getFormatter("dxForm-requiredMessage"),
showValidationSummary: false,
scrollingEnabled: false,
stylingMode: (0, _config.default)().editorStylingMode,
labelMode: "outside",
isDirty: false,
onSmartPasting: null,
onSmartPasted: null
})
}
_defaultOptionsRules() {
return super._defaultOptionsRules().concat([{
device: () => (0, _themes.isMaterialBased)((0, _themes.current)()),
options: {
labelLocation: "top"
}
}, {
device: () => (0, _themes.isMaterial)((0, _themes.current)()),
options: {
showColonAfterLabel: false
}
}])
}
_setOptionsByReference() {
super._setOptionsByReference();
(0, _extend.extend)(this._optionsByReference, {
formData: true,
validationGroup: true
})
}
_getGroupColCount($element) {
return parseInt($element.attr(_constants.GROUP_COL_COUNT_ATTR) ?? "1", 10)
}
_applyLabelsWidthByCol($container, index) {
let options = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {};
const fieldItemClass = null !== options && void 0 !== options && options.inOneColumn ? _constants.FIELD_ITEM_CLASS : _constants.FORM_FIELD_ITEM_COL_CLASS + index;
const cssExcludeTabbedSelector = null !== options && void 0 !== options && options.excludeTabbed ? `:not(.${_constants.FIELD_ITEM_TAB_CLASS})` : "";
(0, _label.setLabelWidthByMaxLabelWidth)($container, `.${fieldItemClass}${cssExcludeTabbedSelector}`)
}
_applyLabelsWidth($container, excludeTabbed, inOneColumn, colCount) {
const applyLabelsOptions = {
excludeTabbed: excludeTabbed,
inOneColumn: inOneColumn
};
const columnsCount = inOneColumn ? 1 : colCount ?? this._getGroupColCount($container);
for (let i = 0; i < columnsCount; i += 1) {
this._applyLabelsWidthByCol($container, i, applyLabelsOptions)
}
}
_getGroupElementsInColumn($container, columnIndex, colCount) {
const cssColCountSelector = (0, _type.isDefined)(colCount) ? `.${_constants.GROUP_COL_COUNT_CLASS}${colCount}` : "";
const groupSelector = `.${_constants.FORM_FIELD_ITEM_COL_CLASS}${columnIndex} > .${_constants.FIELD_ITEM_CONTENT_CLASS} > .${_constants.FORM_GROUP_CLASS}${cssColCountSelector}`;
return $container.find(groupSelector)
}
_applyLabelsWidthWithGroups($container, colCount, excludeTabbed) {
const {
alignRootItemLabels: alignRootItemLabels
} = this.option();
if (true === alignRootItemLabels) {
const $rootSimpleItems = $container.find(`.${_constants.ROOT_SIMPLE_ITEM_CLASS}`);
for (let colIndex = 0; colIndex < colCount; colIndex += 1) {
this._applyLabelsWidthByCol($rootSimpleItems, colIndex)
}
}
const alignItemLabelsInAllGroups = this.option("alignItemLabelsInAllGroups");
if (alignItemLabelsInAllGroups) {
this._applyLabelsWidthWithNestedGroups($container, colCount, excludeTabbed)
} else {
const $groups = this.$element().find(`.${_constants.FORM_GROUP_CLASS}`);
for (let i = 0; i < $groups.length; i += 1) {
this._applyLabelsWidth($groups.eq(i), excludeTabbed, false, void 0)
}
}
}
_applyLabelsWidthWithNestedGroups($container, colCount, excludeTabbed) {
const applyLabelsOptions = {
excludeTabbed: excludeTabbed
};
for (let colIndex = 0; colIndex < colCount; colIndex += 1) {
const $baseGroups = this._getGroupElementsInColumn($container, colIndex);
this._applyLabelsWidthByCol($baseGroups, 0, applyLabelsOptions);
for (let groupsColIndex = 0; groupsColIndex < this._groupsColCount.length; groupsColIndex += 1) {
const $groupsByCol = this._getGroupElementsInColumn($container, colIndex, this._groupsColCount[groupsColIndex]);
const groupColCount = this._getGroupColCount($groupsByCol);
for (let groupColIndex = 1; groupColIndex < groupColCount; groupColIndex += 1) {
this._applyLabelsWidthByCol($groupsByCol, groupColIndex, applyLabelsOptions)
}
}
}
}
_labelLocation() {
const {
labelLocation: labelLocation
} = this.option();
return labelLocation
}
_alignLabelsInColumn(options) {
const {
layoutManager: layoutManager,
inOneColumn: inOneColumn,
$container: $container,
excludeTabbed: excludeTabbed,
items: items
} = options;
if (!(0, _window.hasWindow)() || "top" === this._labelLocation()) {
return
}
if (inOneColumn) {
this._applyLabelsWidth($container, excludeTabbed, true, void 0)
} else if (this._checkGrouping(items)) {
this._applyLabelsWidthWithGroups($container, layoutManager._getColCount(), excludeTabbed)
} else {
this._applyLabelsWidth($container, excludeTabbed, false, layoutManager._getColCount())
}
}
_prepareFormData() {
if (!(0, _type.isDefined)(this.option("formData"))) {
this.option("formData", {})
}
}
_setStylingModeClass() {
const {
stylingMode: stylingMode
} = this.option();
if ("underlined" === stylingMode) {
this.$element().addClass(_constants.FORM_UNDERLINED_CLASS)
}
}
_initMarkup() {
_m_validation_engine.default.addGroup(this._getValidationGroup(), false);
this._clearCachedInstances();
this._prepareFormData();
this.$element().addClass(_constants.FORM_CLASS);
this._setStylingModeClass();
super._initMarkup();
this.setAria("role", "form", this.$element());
const {
scrollingEnabled: scrollingEnabled
} = this.option();
if (scrollingEnabled) {
this._renderScrollable()
}
this._renderLayout();
this._renderValidationSummary();
this._lastMarkupScreenFactor = this._targetScreenFactor || this._getCurrentScreenFactor();
this._attachResizeObserverSubscription()
}
_attachResizeObserverSubscription() {
if ((0, _window.hasWindow)()) {
const formRootElement = this.$element().get(0);
_resize_observer.default.unobserve(formRootElement);
_resize_observer.default.observe(formRootElement, (() => {
this._resizeHandler()
}))
}
}
_resizeHandler() {
if (this._cachedLayoutManagers.length) {
(0, _iterator.each)(this._cachedLayoutManagers, ((_, layoutManager) => {
const {
onLayoutChanged: onLayoutChanged
} = layoutManager.option();
null === onLayoutChanged || void 0 === onLayoutChanged || onLayoutChanged(layoutManager.isSingleColumnMode())
}))
}
}
_getCurrentScreenFactor() {
const {
screenByWidth: screenByWidth
} = this.option();
if ((0, _window.hasWindow)()) {
const currentScreenFactor = (0, _window.getCurrentScreenFactor)(screenByWidth);
return currentScreenFactor
}
return "lg"
}
_clearCachedInstances() {
this._itemsRunTimeInfo.clear();
this._cachedLayoutManagers = []
}
_alignLabels(layoutManager, inOneColumn) {
const {
items: items
} = this.option();
this._alignLabelsInColumn({
$container: this.$element(),
layoutManager: layoutManager,
excludeTabbed: true,
items: items,
inOneColumn: inOneColumn
});
(0, _visibility_change.triggerResizeEvent)(this.$element().find(`.${_constants2.TOOLBAR_CLASS}`))
}
_clean() {
this._clearValidationSummary();
super._clean();
this._groupsColCount = [];
this._cachedColCountOptions = [];
this._lastMarkupScreenFactor = void 0;
_resize_observer.default.unobserve(this.$element().get(0))
}
_renderScrollable() {
const useNativeScrolling = this.option("useNativeScrolling");
this._scrollable = new _scrollable.default(this.$element(), {
useNative: !!useNativeScrolling,
useSimulatedScrollbar: !useNativeScrolling,
useKeyboard: false,
direction: "both",
bounceEnabled: false
})
}
_getContent() {
var _this$_scrollable;
const {
scrollingEnabled: scrollingEnabled
} = this.option();
return scrollingEnabled ? (0, _renderer.default)(null === (_this$_scrollable = this._scrollable) || void 0 === _this$_scrollable ? void 0 : _this$_scrollable.content()) : this.$element()
}
_clearValidationSummary() {
var _this$_$validationSum;
null === (_this$_$validationSum = this._$validationSummary) || void 0 === _this$_$validationSum || _this$_$validationSum.remove();
this._$validationSummary = void 0;
this._validationSummary = void 0
}
_renderValidationSummary() {
this._clearValidationSummary();
const {
showValidationSummary: showValidationSummary
} = this.option();
if (showValidationSummary) {
this._$validationSummary = (0, _renderer.default)("<div>").addClass(_constants.FORM_VALIDATION_SUMMARY).appendTo(this._getContent());
this._validationSummary = super._createComponent(this._$validationSummary, _m_validation_summary.default, {
validationGroup: this._getValidationGroup()
})
}
}
_prepareItems(items, parentIsTabbedItem, currentPath, isTabs) {
if (items) {
const result = [];
for (let i = 0; i < items.length; i += 1) {
let item = items[i];
const path = (0, _form5.concatPaths)(currentPath, (0, _form5.createItemPathByIndex)(i, isTabs));
const itemRunTimeInfo = {
item: item,
itemIndex: i,
path: path
};
const guid = this._itemsRunTimeInfo.add(itemRunTimeInfo);
if ((0, _type.isString)(item)) {
item = {
dataField: item
}
}
if ((0, _type.isObject)(item)) {
const preparedItem = Object.assign({}, item);
itemRunTimeInfo.preparedItem = preparedItem;
preparedItem.guid = guid;
this._tryPrepareGroupItemCaption(preparedItem);
this._tryPrepareGroupItem(preparedItem);
this._tryPrepareTabbedItem(preparedItem, path);
this._tryPrepareItemTemplate(preparedItem);
if (parentIsTabbedItem) {
preparedItem.cssItemClass = _constants.FIELD_ITEM_TAB_CLASS
}
if (preparedItem.items) {
preparedItem.items = this._prepareItems(preparedItem.items, parentIsTabbedItem, path)
}
result.push(preparedItem)
} else {
result.push(item)
}
}
return result
}
return items
}
_isGroupItem(item) {
return "group" === item.itemType
}
_tryPrepareGroupItemCaption(item) {
if (this._isGroupItem(item)) {
item._prepareGroupCaptionTemplate = captionTemplate => {
if (item.captionTemplate) {
item.groupCaptionTemplate = this._getTemplate(captionTemplate)
}
item.captionTemplate = this._itemGroupTemplate.bind(this, item)
};
item._prepareGroupCaptionTemplate(item.captionTemplate)
}
}
_tryPrepareGroupItem(item) {
if (this._isGroupItem(item)) {
item.alignItemLabels = (0, _common.ensureDefined)(item.alignItemLabels, true);
item._prepareGroupItemTemplate = itemTemplate => {
if (item.template) {
item.groupContentTemplate = this._getTemplate(itemTemplate)
}
item.template = this._itemGroupTemplate.bind(this, item)
};
item._prepareGroupItemTemplate(item.template)
}
}
_isTabbedItem(item) {
return "tabbed" === item.itemType
}
_tryPrepareTabbedItem(item, path) {
if (this._isTabbedItem(item)) {
item.template = this._itemTabbedTemplate.bind(this, item);
item.tabs = this._prepareItems(item.tabs, true, path, true)
}
}
_tryPrepareItemTemplate(item) {
if (item.template) {
item.template = this._getTemplate(item.template)
}
}
_checkGrouping(items) {
if (items) {
for (let i = 0; i < items.length; i += 1) {
const item = items[i];
if ("group" === item.itemType) {
return true
}
}
}
return false
}
_renderLayout() {
const {
items: items
} = this.option();
const $content = this._getContent();
const preparedItems = this._prepareItems(items);
const {
colCount: colCount,
alignItemLabels: alignItemLabels,
screenByWidth: screenByWidth,
colCountByScreen: colCountByScreen
} = this.option();
this._rootLayoutManager = this._renderLayoutManager($content, this._createLayoutManagerOptions(preparedItems, {
isRoot: true,
colCount: colCount,
alignItemLabels: alignItemLabels,
screenByWidth: screenByWidth,
colCountByScreen: colCountByScreen,
onLayoutChanged: inOneColumn => {
this._alignLabels.bind(this)(this._rootLayoutManager, inOneColumn)
},
onContentReady: e => {
this._alignLabels(e.component, e.component.isSingleColumnMode())
}
}))
}
_tryGetItemsForTemplate(item) {
return item.items ?? []
}
_itemTabbedTemplate(tabbedItem, data, $itemContainer) {
const $tabPanel = (0, _renderer.default)("<div>").appendTo($itemContainer);
const tabPanelOptions = Object.assign({}, tabbedItem.tabPanelOptions, {
dataSource: tabbedItem.tabs,
onItemRendered: args => {
var _tabbedItem$tabPanelO, _tabbedItem$tabPanelO2;
null === (_tabbedItem$tabPanelO = tabbedItem.tabPanelOptions) || void 0 === _tabbedItem$tabPanelO || null === (_tabbedItem$tabPanelO2 = _tabbedItem$tabPanelO.onItemRendered) || void 0 === _tabbedItem$tabPanelO2 || _tabbedItem$tabPanelO2.call(_tabbedItem$tabPanelO, args);
(0, _visibility_change.triggerShownEvent)(args.itemElement)
},
itemTemplate: (itemData, e, container) => {
const {
screenByWidth: screenByWidth
} = this.option();
const $container = (0, _renderer.default)(container);
const alignItemLabels = (0, _common.ensureDefined)(itemData.alignItemLabels, true);
const layoutManager = this._renderLayoutManager($container, this._createLayoutManagerOptions(this._tryGetItemsForTemplate(itemData), {
colCount: itemData.colCount,
alignItemLabels: alignItemLabels,
screenByWidth: screenByWidth,
colCountByScreen: itemData.colCountByScreen,
cssItemClass: itemData.cssItemClass,
onLayoutChanged: inOneColumn => {
this._alignLabelsInColumn({
$container: (0, _renderer.default)(container),
layoutManager: layoutManager,
items: itemData.items,
inOneColumn: inOneColumn,
excludeTabbed: false
})
}
}));
if (this._itemsRunTimeInfo) {
this._itemsRunTimeInfo.extendRunTimeItemInfoByKey(itemData.guid ?? "", {
layoutManager: layoutManager
})
}
if (alignItemLabels) {
this._alignLabelsInColumn({
$container: $container,
layoutManager: layoutManager,
items: itemData.items,
inOneColumn: layoutManager.isSingleColumnMode(),
excludeTabbed: false
})
}
}
});
const tryUpdateTabPanelInstance = (items, instance) => {
if (Array.isArray(items)) {
items.forEach((item => this._itemsRunTimeInfo.extendRunTimeItemInfoByKey(item.guid ?? "", {
widgetInstance: instance
})))
}
};
const tabPanel = this._createComponent($tabPanel, _tab_panel.default, tabPanelOptions);
(0, _renderer.default)($itemContainer).parent().addClass(_constants.FIELD_ITEM_CONTENT_HAS_TABS_CLASS);
tabPanel.on("optionChanged", (eventArgs => {
const {
fullName: fullName,
value: value,
component: component
} = eventArgs;
if ("dataSource" === fullName) {
tryUpdateTabPanelInstance(value, component)
}
}));
tryUpdateTabPanelInstance([{
guid: tabbedItem.guid
}, ...tabbedItem.tabs ?? []], tabPanel)
}
_itemGroupCaptionTemplate(item, $group, id) {
if (item.groupCaptionTemplate) {
const $captionTemplate = (0, _renderer.default)("<div>").addClass(_constants.FORM_GROUP_CUSTOM_CAPTION_CLASS).attr("id", id).appendTo($group);
item._renderGroupCaptionTemplate = () => {
var _item$groupCaptionTem;
const data = {
component: this,
caption: item.caption,
name: item.name
};
null === (_item$groupCaptionTem = item.groupCaptionTemplate) || void 0 === _item$groupCaptionTem || _item$groupCaptionTem.render({
model: data,
container: (0, _element.getPublicElement)($captionTemplate)
})
};
item._renderGroupCaptionTemplate();
return
}
if (item.caption) {
(0, _renderer.default)("<span>").addClass(_constants.FORM_GROUP_CAPTION_CLASS).text(item.caption).attr("id", id).appendTo($group)
}
}
_itemGroupContentTemplate(item, $group) {
const $groupContent = (0, _renderer.default)("<div>").addClass(_constants.FORM_GROUP_CONTENT_CLASS).appendTo($group);
if (item.groupContentTemplate) {
item._renderGroupContentTemplate = () => {
var _item$groupContentTem;
$groupContent.empty();
const data = {
formData: this.option("formData"),
component: this
};
null === (_item$groupContentTem = item.groupContentTemplate) || void 0 === _item$groupContentTem || _item$groupContentTem.render({
model: data,
container: (0, _element.getPublicElement)($groupContent)
})
};
item._renderGroupContentTemplate()
} else {
var _this$_itemsRunTimeIn;
const layoutManager = this._renderLayoutManager($groupContent, this._createLayoutManagerOptions(this._tryGetItemsForTemplate(item), {
colCount: item.colCount,
colCountByScreen: item.colCountByScreen,
alignItemLabels: item.alignItemLabels,
cssItemClass: item.cssItemClass
}));
null === (_this$_itemsRunTimeIn = this._itemsRunTimeInfo) || void 0 === _this$_itemsRunTimeIn || _this$_itemsRunTimeIn.extendRunTimeItemInfoByKey(item.guid ?? "", {
layoutManager: layoutManager
});
const colCount = layoutManager._getColCount();
if (!this._groupsColCount.includes(colCount)) {
this._groupsColCount.push(colCount)
}
$group.addClass(_constants.GROUP_COL_COUNT_CLASS + colCount);
$group.attr(_constants.GROUP_COL_COUNT_ATTR, colCount)
}
}
_itemGroupTemplate(item, options, $container) {
var _item$caption;
const {
id: id
} = options.editorOptions.inputAttr;
const $group = (0, _renderer.default)("<div>").toggleClass(_constants.FORM_GROUP_WITH_CAPTION_CLASS, !!(null !== (_item$caption = item.caption) && void 0 !== _item$caption && _item$caption.length)).addClass(_constants.FORM_GROUP_CLASS).appendTo($container);
const groupAria = {
role: "group",
labelledby: id
};
this.setAria(groupAria, $group);
(0, _renderer.default)($container).parent().addClass(_constants.FIELD_ITEM_CONTENT_HAS_GROUP_CLASS);
this._itemGroupCaptionTemplate(item, $group, id);
this._itemGroupContentTemplate(item, $group)
}
_createLayoutManagerOptions(items, extendedLayoutManagerOptions) {
return (0, _form5.convertToLayoutManagerOptions)({
form: this,
formOptions: this.option(),
$formElement: this.$element(),
items: items,
validationGroup: this._getValidationGroup(),
extendedLayoutManagerOptions: extendedLayoutManagerOptions,
onFieldDataChanged: args => {
if (!this._isDataUpdating) {
this._triggerOnFieldDataChanged(args)
}
},
onContentReady: args => {
var _extendedLayoutManage;
this._itemsRunTimeInfo.addItemsOrExtendFrom(args.component._itemsRunTimeInfo);
null === (_extendedLayoutManage = extendedLayoutManagerOptions.onContentReady) || void 0 === _extendedLayoutManage || _extendedLayoutManage.call(extendedLayoutManagerOptions, args)
},
onDisposing: e => {
const {
component: component
} = e;
const nestedItemsRunTimeInfo = component.getItemsRunTimeInfo();
this._itemsRunTimeInfo.removeItemsByItems(nestedItemsRunTimeInfo)
},
onFieldItemRendered: () => {
var _this$_validationSumm;
null === (_this$_validationSumm = this._validationSummary) || void 0 === _this$_validationSumm || _this$_validationSumm.refreshValidationGroup()
}
})
}
_renderLayoutManager($parent, layoutManagerOptions) {
const baseColCountByScreen = {
lg: layoutManagerOptions.colCount,
md: layoutManagerOptions.colCount,
sm: layoutManagerOptions.colCount,
xs: 1
};
this._cachedColCountOptions.push({
colCountByScreen: (0, _extend.extend)(baseColCountByScreen, layoutManagerOptions.colCountByScreen)
});
const $element = (0, _renderer.default)("<div>");
$element.appendTo($parent);
const instance = this._createComponent($element, _form3.default, layoutManagerOptions);
instance.on("autoColCountChanged", (() => {
this._clearAutoColCountChangedTimeout();
this.autoColCountChangedTimeoutId = setTimeout((() => !this._disposed && this._refresh()), 0)
}));
this._cachedLayoutManagers.push(instance);
return instance
}
_getValidationGroup() {
const {
validationGroup: validationGroup
} = this.option();
return validationGroup ?? this
}
_createComponent(element, component, componentConfiguration) {
const {
readOnly: readOnly
} = this.option();
this._extendConfig(componentConfiguration ?? {}, {
readOnly: readOnly
});
return super._createComponent(element, component, componentConfiguration)
}
_attachSyncSubscriptions() {
this.on("optionChanged", (args => {
const {
fullName: fullName,
name: name
} = args;
if ("formData" === fullName) {
if (!(0, _type.isDefined)(args.value)) {
this._options.silent("formData", args.value = {})
}
this._triggerOnFieldDataChangedByDataSet(args.value)
}
if (this._cachedLayoutManagers.length) {
(0, _iterator.each)(this._cachedLayoutManagers, ((_index, layoutManager) => {
if ("formData" === fullName) {
this._isDataUpdating = true;
layoutManager.option("layoutData", args.value);
this._isDataUpdating = false
}
if ("readOnly" === name || "disabled" === name) {
layoutManager.option(fullName, args.value)
}
}))
}
}))
}
_createSmartPastingAction() {
this._smartPastingAction = this._createActionByOption("onSmartPasting", {
excludeValidators: ["disabled"]
})
}
_createSmartPastedAction() {
this._smartPastedAction = this._createActionByOption("onSmartPasted", {
excludeValidators: ["disabled"]
})
}
_optionChanged(args) {
const {
fullName: fullName
} = args;
const splitFullName = fullName.split(".");
if (splitFullName.length > 1 && -1 !== splitFullName[0].search("items") && this._itemsOptionChangedHandler(args)) {
return
}
if (splitFullName.length > 1 && -1 !== splitFullName[0].search("formData") && this._formDataOptionChangedHandler(args)) {
return
}
this._defaultOptionChangedHandler(args)
}
_defaultOptionChangedHandler(args) {
switch (args.name) {
case "formData":
if (!this.option("items")) {
this._invalidate()
} else if ((0, _type.isEmptyObject)(args.value)) {
this._clear()
}
break;
case "onFieldDataChanged":
case "alignRootItemLabels":
case "readOnly":
case "isDirty":
break;
case "items":
case "colCount":
case "onEditorEnterKey":
case "labelLocation":
case "labelMode":
case "alignItemLabels":
case "showColonAfterLabel":
case "customizeItem":
case "alignItemLabelsInAllGroups":
case "showRequiredMark":
case "showOptionalMark":
case "requiredMark":
case "optionalMark":
case "requiredMessage":
case "scrollingEnabled":
case "formID":
case "colCountByScreen":
case "screenByWidth":
case "stylingMode":
this._invalidate();
break;
case "showValidationSummary":
this._renderValidationSummary();
break;
case "minColWidth": {
const {
colCount: colCount
} = this.option();
if ("auto" === colCount) {
this._invalidate()
}
break
}
case "width":
super._optionChanged(args);
this._rootLayoutManager.option(args.name, args.value);
this._alignLabels(this._rootLayoutManager, this._rootLayoutManager.isSingleColumnMode());
break;
case "validationGroup":
_m_validation_engine.default.removeGroup(args.previousValue || this);
this._invalidate();
break;
case "aiIntegration":
this._processAIIntegrationUpdate();
break;
case "onSmartPasting":
this._createSmartPastingAction();
break;
case "onSmartPasted":
this._createSmartPastedAction();
break;
default:
super._optionChanged(args)
}
}
_itemsOptionChangedHandler(args) {
const {
value: value,
fullName: fullName
} = args;
const nameParts = fullName.split(".");
const itemPath = this._getItemPath(nameParts);
const item = this.option(itemPath);
const optionNameWithoutPath = fullName.replace(`${itemPath}.`, "");
const simpleOptionName = optionNameWithoutPath.split(".")[0].replace(/\[\d+]/, "");
const itemAction = this._tryCreateItemOptionAction(simpleOptionName, item, item[simpleOptionName], args.previousValue, itemPath);
let result = this._tryExecuteItemOptionAction(itemAction) ?? this._tryChangeLayoutManagerItemOption(fullName, value);
if (!result && item) {
this._changeItemOption(item, optionNameWithoutPath, value);
const {
items: items
} = this.option();
const generatedItems = this._generateItemsFromData(items);
this.option("items", generatedItems);
result = true
}
return result
}
_formDataOptionChangedHandler(args) {
const nameParts = args.fullName.split(".");
const {
value: value
} = args;
const dataField = nameParts.slice(1).join(".");
const editor = this.getEditor(dataField);
if (editor) {
editor.option("value", value)
} else {
this._triggerOnFieldDataChanged({
dataField: dataField,
value: value
})
}
return true
}
_tryCreateItemOptionAction(optionName, item, value, previousValue, itemPath) {
let currentValue = value;
if ("tabs" === optionName) {
this._itemsRunTimeInfo.removeItemsByPathStartWith(`${itemPath}.tabs`);
currentValue = this._prepareItems(currentValue, true, itemPath, true)
}
return (0, _form.default)(optionName, {
item: item,
value: currentValue,
previousValue: previousValue,
itemsRunTimeInfo: this._itemsRunTimeInfo
})
}
_tryExecuteItemOptionAction(action) {
return null === action || void 0 === action ? void 0 : action.tryExecute()
}
_updateValidationGroupAndSummaryIfNeeded(fullName) {
const optionName = (0, _form5.getOptionNameFromFullName)(fullName);
if (ITEM_OPTIONS_FOR_VALIDATION_UPDATING.includes(optionName)) {
_m_validation_engine.default.addGroup(this._getValidationGroup(), false);
if (this.option("showValidationSummary")) {
var _this$_validationSumm2;
null === (_this$_validationSumm2 = this._validationSummary) || void 0 === _this$_validationSumm2 || _this$_validationSumm2.refreshValidationGroup()
}
}
}
_setLayoutManagerItemOption(layoutManager, optionName, value, path) {
if (this._updateLockCount > 0) {
if (!layoutManager._updateLockCount) {
layoutManager.beginUpdate()
}
const key = this._itemsRunTimeInfo.findKeyByPath(path);
this.postponedOperations.add(key, (() => {
if (!layoutManager._disposed) {
layoutManager.endUpdate()
}
return (0, _deferred.Deferred)().resolve()
}))
}
const contentReadyHandler = e => {
e.component.off("contentReady", contentReadyHandler);
if ((0, _form5.isFullPathContainsTabs)(path)) {
const tabPath = (0, _form5.tryGetTabPath)(path);
const tabLayoutManager = this._itemsRunTimeInfo.findGroupOrTabLayoutManagerByPath(tabPath);
if (tabLayoutManager) {
const {
items: items
} = tabLayoutManager.option();
this._alignLabelsInColumn({
items: items,
layoutManager: tabLayoutManager,
$container: tabLayoutManager.$element(),
inOneColumn: tabLayoutManager.isSingleColumnMode(),
excludeTabbed: false
})
}
} else {
this._alignLabels(this._rootLayoutManager, this._rootLayoutManager.isSingleColumnMode())
}
};
layoutManager.on("contentReady", contentReadyHandler);
layoutManager.option(optionName, value);
this._updateValidationGroupAndSummaryIfNeeded(optionName)
}
_tryChangeLayoutManagerItemOption(fullName, value) {
const nameParts = fullName.split(".");
const optionName = (0, _form5.getOptionNameFromFullName)(fullName);
if ("items" === optionName && nameParts.length > 1) {
const itemPath = this._getItemPath(nameParts);
const layoutManager = this._itemsRunTimeInfo.findGroupOrTabLayoutManagerByPath(itemPath);
if (layoutManager) {
this._itemsRunTimeInfo.removeItemsByItems(layoutManager.getItemsRunTimeInfo());
const items = this._prepareItems(value, false, itemPath);
this._setLayoutManagerItemOption(layoutManager, optionName, items, itemPath);
return true
}
} else if (nameParts.length > 2) {
const endPartIndex = nameParts.length - 2;
const itemPath = this._getItemPath(nameParts.slice(0, endPartIndex));
const layoutManager = this._itemsRunTimeInfo.findGroupOrTabLayoutManagerByPath(itemPath);
if (layoutManager) {
const fullOptionName = (0, _form5.getFullOptionName)(nameParts[endPartIndex], optionName);
if ("editorType" === optionName) {
if (layoutManager.option(fullOptionName) !== value) {
return false
}
}
if ("visible" === optionName) {
const formItems = this.option((0, _form5.getFullOptionName)(itemPath, "items"));
if (null !== formItems && void 0 !== formItems && formItems.length) {
const {
items: layoutManagerItems
} = layoutManager.option();
formItems.forEach(((item, index) => {
const layoutItem = layoutManagerItems[index];
layoutItem.visibleIndex = item.visibleIndex
}))
}
}
this._setLayoutManagerItemOption(layoutManager, fullOptionName, value, itemPath);
return true
}
}
return false
}
_tryChangeLayoutManagerItemOptions(itemPath, options) {
let result = false;
this.beginUpdate();
(0, _iterator.each)(options, ((optionName, optionValue) => {
result = this._tryChangeLayoutManagerItemOption((0, _form5.getFullOptionName)(itemPath, optionName), optionValue);
if (!result) {
return false
}
return true
}));
this.endUpdate();
return result
}
_getItemPath(nameParts) {
let itemPath = nameParts[0];
for (let i = 1; i < nameParts.length; i += 1) {
if (-1 !== nameParts[i].search(/items\[\d+]|tabs\[\d+]/)) {
itemPath += `.${nameParts[i]}`
} else {
break
}
}
return itemPath
}
_triggerOnFieldDataChanged(args) {
this._updateIsDirty(args.dataField ?? "");
this._createActionByOption("onFieldDataChanged")(args)
}
_triggerOnFieldDataChangedByDataSet(data) {
if (data && (0, _type.isObject)(data)) {
Object.keys(data).forEach((key => {
this._triggerOnFieldDataChanged({
dataField: key,
value: data[key]
})
}))
}
}
_updateFieldValue(dataField, value) {
const {
formData: formData
} = this.option();
if ((0, _type.isDefined)(formData)) {
const editor = this.getEditor(dataField);
this.option(`formData.${dataField}`, value);
if (editor) {
const editorValue = editor.option("value");
if (editorValue !== value) {
editor.option("value", value)
}
}
}
}
_generateItemsFromData(items) {
const {
formData: formData
} = this.option();
const result = [];
if (!items && (0, _type.isDefined)(formData)) {
(0, _iterator.each)(formData, (dataField => {
result.push({
dataField: dataField
})
}))
}
if (items) {
(0, _iterator.each)(items, ((_index, item) => {
if ((0, _type.isObject)(item)) {
result.push(item)
} else {
result.push({
dataField: item
})
}
}))
}
return result
}
_getItemByField(field, items) {
const fieldParts = (0, _type.isObject)(field) ? field : this._getFieldParts(field);
const {
fieldName: fieldName
} = fieldParts;
const {
fieldPath: fieldPath
} = fieldParts;
let resultItem = null;
if (items.length) {
(0, _iterator.each)(items, ((_index, item) => {
const {
itemType: itemType
} = item;
if (fieldPath.length) {
const path = fieldPath.slice();
item = this._getItemByFieldPath(path, fieldName, item)
} else if (this._isGroupItem(item) && !(item.caption || item.name) || "tabbed" === itemType && !item.name) {
const subItemsField = this._getSubItemField(itemType);
item.items = this._generateItemsFromData(item.items);
item = this._getItemByField({
fieldName: fieldName,
fieldPath: fieldPath
}, item[subItemsField])
}
if ((0, _form5.isEqualToDataFieldOrNameOrTitleOrCaption)(item, fieldName)) {
resultItem = item;
return false
}
return true
}))
}
return resultItem
}
_getFieldParts(field) {
const [fieldName, ...fieldPath] = field.split(".").reverse();
return {
fieldName: fieldName,
fieldPath: fieldPath
}
}
_getItemByFieldPath(path, fieldName, item) {
const {
itemType: itemType
} = item;
const subItemsField = this._getSubItemField(itemType);
const isItemWithSubItems = "group" === itemType || "tabbed" === itemType || item.title;
let result = null;
do {
if (isItemWithSubItems) {
const name = item.name || item.caption || item.title;
const isGroupWithName = (0, _type.isDefined)(name);
const nameWithoutSpaces = (0, _form5.getTextWithoutSpaces)(name);
let pathNode = "";
item[subItemsField] = this._generateItemsFromData(item[subItemsField]);
if (isGroupWithName) {
pathNode = path.pop()
}
if (!path.length && nameWithoutSpaces === pathNode) {
result = this._getItemByField(fieldName, item[subItemsField]);
if (result) {
break
}
}
const isGroupPathNodeOrUnnamed = !isGroupWithName || isGroupWithName && nameWithoutSpaces === pathNode;
if (isGroupPathNodeOrUnnamed && path.length) {
result = this._searchItemInEverySubItem(path, fieldName, item[subItemsField]);
if (!result) {
break
}
}
} else {
break
}
} while (path.length && !(0, _type.isDefined)(result));
return result
}
_getSubItemField(itemType) {
return "tabbed" === itemType ? "tabs" : "items"
}
_searchItemInEverySubItem(path, fieldName, items) {
let result = null;
(0, _iterator.each)(items, ((_index, groupItem) => {
result = this._getItemByFieldPath(path.slice(), fieldName, groupItem);
if (result) {
return false
}
return true
}));
return result
}
_changeItemOption(item, option, value) {
if ((0, _type.isObject)(item)) {
item[option] = value
}
}
_dimensionChanged() {
const currentScreenFactor = this._getCurrentScreenFactor();
if (this._lastMarkupScreenFactor !== currentScreenFactor) {
if (this._isColCountChanged(this._lastMarkupScreenFactor, currentScreenFactor)) {
this._targetScreenFactor = currentScreenFactor;
this._refresh();
this._targetScreenFactor = void 0
}
this._lastMarkupScreenFactor = currentScreenFactor
}
}
_isColCountChanged(oldScreenSize, newScreenSize) {
let isChanged = false;
(0, _iterator.each)(this._cachedColCountOptions, ((_index, item) => {
if (item.colCountByScreen[oldScreenSize] !== item.colCountByScreen[newScreenSize]) {
isChanged = true;
return false
}
return true
}));
return isChanged
}
_refresh() {
const editorSelector = `.${_m_text_editor.TEXTEDIT