devextreme
Version:
JavaScript/TypeScript Component Suite for Responsive Web Development
202 lines (199 loc) • 11 kB
JavaScript
/**
* DevExtreme (cjs/__internal/integration/knockout/component_registrator.js)
* Version: 25.2.7
* Build date: Tue May 05 2026
*
* Copyright (c) 2012 - 2026 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
;
var _renderer = _interopRequireDefault(require("../../../core/renderer"));
var _ui = _interopRequireDefault(require("../../../ui/widget/ui.widget"));
var _m_component_registrator_callbacks = require("../../core/m_component_registrator_callbacks");
var _m_config = _interopRequireDefault(require("../../core/m_config"));
var _component_wrapper = require("../../core/r1/component_wrapper");
var _m_callbacks = _interopRequireDefault(require("../../core/utils/m_callbacks"));
var _m_locker = require("../../core/utils/m_locker");
var _m_type = require("../../core/utils/m_type");
var _m_draggable = _interopRequireDefault(require("../../m_draggable"));
var _editor = _interopRequireDefault(require("../../ui/editor/editor"));
var _scroll_view = _interopRequireDefault(require("../../ui/scroll_view/scroll_view"));
var _m_base_widget = _interopRequireDefault(require("../../viz/core/m_base_widget"));
var _knockout = _interopRequireDefault(require("knockout"));
var _template = require("./template");
var _utils = require("./utils");
function _interopRequireDefault(e) {
return e && e.__esModule ? e : {
default: e
}
}
if (_knockout.default) {
const LOCKS_DATA_KEY = "dxKoLocks";
const CREATED_WITH_KO_DATA_KEY = "dxKoCreation";
const editorsBindingHandlers = [];
const registerComponentKoBinding = function(componentName, componentClass) {
if (_editor.default.isEditor(componentClass.prototype)) {
editorsBindingHandlers.push(componentName)
}
_knockout.default.bindingHandlers[componentName] = {
init(domNode, valueAccessor) {
const $element = (0, _renderer.default)(domNode);
const optionChangedCallbacks = (0, _m_callbacks.default)();
let optionsByReference = {};
let component;
const knockoutConfig = (0, _m_config.default)().knockout;
const isBindingPropertyPredicateName = null === knockoutConfig || void 0 === knockoutConfig ? void 0 : knockoutConfig.isBindingPropertyPredicateName;
let isBindingPropertyPredicate;
let ctorOptions = {
onInitializing(options) {
optionsByReference = this._getOptionsByReference();
_knockout.default.computed(() => {
const model = _knockout.default.unwrap(valueAccessor());
if (component) {
component.beginUpdate()
}
isBindingPropertyPredicate = isBindingPropertyPredicateName && (null === model || void 0 === model ? void 0 : model[isBindingPropertyPredicateName]);
unwrapModel(model);
if (component) {
component.endUpdate()
} else {
var _model$onInitializing;
null === model || void 0 === model || null === (_model$onInitializing = model.onInitializing) || void 0 === _model$onInitializing || _model$onInitializing.call(this, options)
}
}, null, {
disposeWhenNodeIsRemoved: domNode
});
component = this
},
modelByElement($element) {
if ($element.length) {
const node = (0, _utils.getClosestNodeWithContext)($element.get(0));
return _knockout.default.dataFor(node)
}
},
nestedComponentOptions: component => ({
modelByElement: component.option("modelByElement"),
nestedComponentOptions: component.option("nestedComponentOptions")
}),
_optionChangedCallbacks: optionChangedCallbacks,
integrationOptions: {
watchMethod(fn, callback, options) {
options = options || {};
let skipCallback = options.skipImmediate;
const watcher = _knockout.default.computed(() => {
const newValue = _knockout.default.unwrap(fn());
if (!skipCallback) {
callback(newValue)
}
skipCallback = false
});
return function() {
watcher.dispose()
}
},
templates: {
"dx-polymorph-widget": {
render(options) {
const widgetName = _knockout.default.utils.unwrapObservable(options.model.widget);
if (!widgetName) {
return
}
const markup = (0, _renderer.default)("<div>").attr("data-bind", `${widgetName}: options`).get(0);
(0, _renderer.default)(options.container).append(markup);
_knockout.default.applyBindings(options.model, markup)
}
}
},
createTemplate: element => new _template.KoTemplate(element)
}
};
const optionNameToModelMap = {};
const applyModelValueToOption = function(optionName, modelValue, unwrap) {
const locks = $element.data(LOCKS_DATA_KEY);
const optionValue = unwrap ? _knockout.default.unwrap(modelValue) : modelValue;
if (_knockout.default.isWriteableObservable(modelValue)) {
optionNameToModelMap[optionName] = modelValue
}
if (component) {
if (locks.locked(optionName)) {
return
}
locks.obtain(optionName);
try {
if (_knockout.default.ignoreDependencies) {
_knockout.default.ignoreDependencies(component.option, component, [optionName, optionValue])
} else {
component.option(optionName, optionValue)
}
} finally {
locks.release(optionName)
}
} else {
ctorOptions[optionName] = optionValue
}
};
const handleOptionChanged = function(args) {
const optionName = args.fullName;
const optionValue = args.value;
if (!(optionName in optionNameToModelMap)) {
return
}
const $element = this._$element;
const locks = $element.data(LOCKS_DATA_KEY);
if (locks.locked(optionName)) {
return
}
locks.obtain(optionName);
try {
optionNameToModelMap[optionName](optionValue)
} finally {
locks.release(optionName)
}
};
const unwrapModelValue = function(currentModel, propertyName, propertyPath) {
if (propertyPath === isBindingPropertyPredicateName) {
return
}
if (!isBindingPropertyPredicate || isBindingPropertyPredicate(propertyPath, propertyName, currentModel)) {
let unwrappedPropertyValue;
_knockout.default.computed(() => {
const propertyValue = currentModel[propertyName];
applyModelValueToOption(propertyPath, propertyValue, true);
unwrappedPropertyValue = _knockout.default.unwrap(propertyValue)
}, null, {
disposeWhenNodeIsRemoved: domNode
});
if ((0, _m_type.isPlainObject)(unwrappedPropertyValue)) {
if (!optionsByReference[propertyPath]) {
unwrapModel(unwrappedPropertyValue, propertyPath)
}
}
} else {
applyModelValueToOption(propertyPath, currentModel[propertyName], false)
}
};
function unwrapModel(model, propertyPath) {
for (const propertyName in model) {
if (Object.prototype.hasOwnProperty.call(model, propertyName)) {
unwrapModelValue(model, propertyName, propertyPath ? [propertyPath, propertyName].join(".") : propertyName)
}
}
}! function() {
optionChangedCallbacks.add(handleOptionChanged);
$element.data(CREATED_WITH_KO_DATA_KEY, true).data(LOCKS_DATA_KEY, new _m_locker.Locker);
new componentClass($element, ctorOptions);
ctorOptions = null
}();
return {
controlsDescendantBindings: componentClass.subclassOf(_ui.default) || componentClass.subclassOf(_m_base_widget.default) || componentClass.subclassOf(_component_wrapper.ComponentWrapper) && !(component instanceof _scroll_view.default) || component instanceof _m_draggable.default
}
}
};
if ("dxValidator" === componentName) {
_knockout.default.bindingHandlers.dxValidator.after = editorsBindingHandlers
}
};
_m_component_registrator_callbacks.componentRegistratorCallbacks.add((name, componentClass) => {
registerComponentKoBinding(name, componentClass)
})
}