devextreme-vue
Version:
DevExtreme Vue UI and Visualization Components
321 lines (319 loc) • 14.1 kB
JavaScript
/*!
* devextreme-vue
* Version: 25.1.6
* Build date: Mon Oct 13 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file in the root of the project for details.
*
* https://github.com/DevExpress/devextreme-vue
*/
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.initBaseComponent = exports.initDxComponent = void 0;
const vue_1 = require("vue");
const callbacks_1 = __importDefault(require("devextreme/core/utils/callbacks"));
const events_1 = require("devextreme/events");
const config_1 = __importDefault(require("devextreme/core/config"));
const vue_helper_1 = require("./vue-helper");
const children_processing_1 = require("./children-processing");
const configuration_1 = __importStar(require("./configuration"));
const configuration_component_1 = require("./configuration-component");
const constants_1 = require("./constants");
const helpers_1 = require("./helpers");
const templates_manager_1 = require("./templates-manager");
const includeAttrs = ['id', 'class', 'style'];
const dxClassesPrefix = 'dx-';
(0, config_1.default)({
buyNowLink: 'https://go.devexpress.com/Licensing_Installer_Watermark_DevExtremeVue.aspx',
licensingDocLink: 'https://go.devexpress.com/Licensing_Documentation_DevExtremeVue.aspx',
});
function parseClassList(classList) {
return classList.trim().split(/\s+/);
}
function prepareAttrs(attrs, dxClassesSyncedWithClassAttr) {
const attributes = {};
includeAttrs.forEach((attr) => {
const attrValue = attrs[attr];
if (attrValue !== undefined && attrValue !== null) {
if (attr === 'class') {
const nonDXClassesFromAttr = attrValue.split(' ')
.filter((classFromAttr) => !classFromAttr.startsWith(dxClassesPrefix))
.join(' ');
attributes[attr] = [nonDXClassesFromAttr, dxClassesSyncedWithClassAttr].filter((item) => item !== '').join(' ');
}
else {
attributes[attr] = attrValue;
}
}
});
return attributes;
}
function initBaseComponent() {
return (0, vue_1.defineComponent)({
inheritAttrs: false,
data() {
return {
eventBus: (0, callbacks_1.default)(),
prevClassAttr: '',
};
},
provide() {
return {
eventBus: this.eventBus,
};
},
render() {
const thisComponent = this;
const children = [];
const dxClasses = pickOutDxClasses(this.$el) || [];
if (thisComponent.$_config.cleanNested) {
thisComponent.$_config.cleanNested();
}
(0, children_processing_1.pullAllChildren)((0, vue_helper_1.defaultSlots)(this), children, thisComponent.$_config);
this.$_processChildren(children);
return (0, vue_1.h)('div', {
...prepareAttrs(this.$attrs, dxClasses.join(' ')),
}, children);
},
beforeUpdate() {
const thisComponent = this;
thisComponent.$_config.setPrevNestedOptions(thisComponent.$_config.getNestedOptionValues());
this.$_syncElementClassesWithClassAttr();
},
updated() {
const thisComponent = this;
const nodes = cleanWidgetNode(this.$el);
(0, vue_helper_1.getChildren)(thisComponent).forEach((child) => {
(0, configuration_component_1.initOptionChangedFunc)(child.$_config, child.type.props || {}, child?.component?.proxy, child.$_innerChanges);
});
thisComponent.$_templatesManager.discover();
thisComponent.$_instance.beginUpdate();
this.$_applyConfigurationChanges();
if (thisComponent.$_templatesManager.isDirty) {
thisComponent.$_instance.option('integrationOptions.templates', thisComponent.$_templatesManager.templates);
const { props } = thisComponent.$.vnode;
for (const name of Object.keys(thisComponent.$_templatesManager.templates)) {
thisComponent.$_instance.option((0, helpers_1.getTemplatePropName)(props, name), name);
}
thisComponent.$_templatesManager.resetDirtyFlag();
}
for (const name of Object.keys(thisComponent.$_pendingOptions)) {
thisComponent.$_instance.option(name, thisComponent.$_pendingOptions[name]);
}
thisComponent.$_pendingOptions = {};
thisComponent.$_instance.endUpdate();
restoreNodes(this.$el, nodes);
this.eventBus.fire();
},
beforeUnmount() {
const thisComponent = this;
const instance = thisComponent.$_instance;
if (instance) {
(0, events_1.triggerHandler)(this.$el, constants_1.DX_REMOVE_EVENT);
instance.dispose();
}
},
created() {
const thisComponent = this;
const props = (0, vue_helper_1.getComponentProps)(this);
thisComponent.$_config = new configuration_1.default((n, v) => {
if (Array.isArray(v)) {
thisComponent.$_instance.option(n, v);
}
else {
thisComponent.$_pendingOptions[n === vue_helper_1.VMODEL_NAME ? 'value' : n] = v;
}
}, null, props && { ...props }, thisComponent.$_expectedChildren);
thisComponent.$_innerChanges = {};
thisComponent.$_config.init(this.$props && Object.keys(this.$props));
},
methods: {
$_syncElementClassesWithClassAttr() {
const newClassAttr = typeof this.$attrs?.class === 'string' ? this.$attrs?.class : '';
if (this.prevClassAttr === newClassAttr) {
return;
}
if (this.prevClassAttr.length) {
this.$el.classList.remove(...parseClassList(this.prevClassAttr));
}
if (newClassAttr.length) {
this.$el.classList.add(...parseClassList(newClassAttr));
}
this.prevClassAttr = newClassAttr;
},
$_applyConfigurationChanges() {
const thisComponent = this;
thisComponent.$_config.componentsCountChanged.forEach(({ optionPath, isCollection, removed }) => {
const options = thisComponent.$_config.getNestedOptionValues();
if (!isCollection && removed) {
thisComponent.$_instance.resetOption(optionPath);
}
else {
thisComponent.$_instance.option(optionPath, (0, helpers_1.getOptionValue)(options, optionPath));
}
});
thisComponent.$_config.cleanComponentsCountChanged();
},
$_createWidget(element) {
const thisComponent = this;
thisComponent.$_pendingOptions = {};
thisComponent.$_templatesManager = new templates_manager_1.TemplatesManager(this);
const widgetConfig = thisComponent.$_config;
if (widgetConfig.initialValues.hasOwnProperty(vue_helper_1.VMODEL_NAME)) {
widgetConfig.initialValues.value = (0, vue_helper_1.getVModelValue)(widgetConfig.initialValues);
}
const options = {
templatesRenderAsynchronously: thisComponent.$_hasAsyncTemplate,
...(0, vue_helper_1.getComponentProps)(thisComponent),
...widgetConfig.initialValues,
...widgetConfig.getNestedOptionValues(),
...this.$_getIntegrationOptions(),
};
const instance = new thisComponent.$_WidgetClass(element, options);
thisComponent.$_instance = instance;
instance.on('optionChanged', (args) => widgetConfig.onOptionChanged(args));
(0, configuration_1.setEmitOptionChangedFunc)(widgetConfig, thisComponent, thisComponent.$_innerChanges);
(0, configuration_1.bindOptionWatchers)(widgetConfig, thisComponent, thisComponent.$_innerChanges);
this.$_createEmitters(instance);
},
$_getIntegrationOptions() {
const thisComponent = this;
const result = {
integrationOptions: {
watchMethod: this.$_getWatchMethod(),
},
...this.$_getExtraIntegrationOptions(),
};
if (thisComponent.$_templatesManager.isDirty) {
const { templates } = thisComponent.$_templatesManager;
result.integrationOptions.templates = templates;
const { props } = thisComponent.$.vnode;
for (const name of Object.keys(templates)) {
result[(0, helpers_1.getTemplatePropName)(props, name)] = name;
}
thisComponent.$_templatesManager.resetDirtyFlag();
}
return result;
},
$_getWatchMethod() {
return (valueGetter, valueChangeCallback, options) => {
options = options || {};
if (!options.skipImmediate) {
valueChangeCallback(valueGetter());
}
return this.$watch(() => valueGetter(), (newValue, oldValue) => {
if ((0, helpers_1.toComparable)(oldValue) !== (0, helpers_1.toComparable)(newValue) || options.deep) {
valueChangeCallback(newValue);
}
}, {
deep: options.deep,
});
};
},
$_getExtraIntegrationOptions() {
return {};
},
$_processChildren(_children) {
},
$_createEmitters(instance) {
if (this.$attrs) {
Object.keys(this.$attrs).forEach((listenerName) => {
const eventName = (0, helpers_1.camelize)(listenerName);
instance.on(eventName, (e) => {
this.$emit(listenerName, e);
});
});
}
},
},
});
}
exports.initBaseComponent = initBaseComponent;
function cleanWidgetNode(node) {
const removedNodes = [];
(0, helpers_1.forEachChildNode)(node, (childNode) => {
const parent = childNode.parentNode;
const isExtension = childNode.hasAttribute && childNode.hasAttribute('isExtension');
if ((childNode.nodeName === '#comment' || isExtension) && parent) {
removedNodes.push(childNode);
parent.removeChild(childNode);
}
});
return removedNodes;
}
function pickOutDxClasses(el) {
return el && Array.from(el.classList).filter((item) => item.startsWith(dxClassesPrefix));
}
function restoreNodes(el, nodes) {
nodes.forEach((node) => {
el.appendChild(node);
});
}
function initDxComponent() {
return (0, vue_1.defineComponent)({
extends: initBaseComponent(),
methods: {
$_getExtraIntegrationOptions() {
return {
onInitializing() {
this.beginUpdate();
},
};
},
$_processChildren(children) {
children.forEach((childNode) => {
if (!childNode || typeof childNode !== 'object') {
return;
}
childNode.$_hasOwner = true;
});
},
},
mounted() {
const nodes = cleanWidgetNode(this.$el);
const thisComponent = this;
this.$_createWidget(this.$el);
this.$_syncElementClassesWithClassAttr();
thisComponent.$_instance.endUpdate();
restoreNodes(this.$el, nodes);
if (this.$slots?.default) {
(0, vue_helper_1.getChildren)(thisComponent).forEach((child) => {
const childExtenton = child;
if (childExtenton && childExtenton.$_isExtension) {
childExtenton.$_attachTo(this.$el);
}
});
}
},
});
}
exports.initDxComponent = initDxComponent;