component_registrator.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /**
  2. * DevExtreme (integration/angular/component_registrator.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var _renderer = require("../../core/renderer");
  11. var _renderer2 = _interopRequireDefault(_renderer);
  12. var _events_engine = require("../../events/core/events_engine");
  13. var _events_engine2 = _interopRequireDefault(_events_engine);
  14. var _config = require("../../core/config");
  15. var _config2 = _interopRequireDefault(_config);
  16. var _component_registrator_callbacks = require("../../core/component_registrator_callbacks");
  17. var _component_registrator_callbacks2 = _interopRequireDefault(_component_registrator_callbacks);
  18. var _class = require("../../core/class");
  19. var _class2 = _interopRequireDefault(_class);
  20. var _callbacks = require("../../core/utils/callbacks");
  21. var _callbacks2 = _interopRequireDefault(_callbacks);
  22. var _type = require("../../core/utils/type");
  23. var _type2 = _interopRequireDefault(_type);
  24. var _iterator = require("../../core/utils/iterator");
  25. var _iterator2 = _interopRequireDefault(_iterator);
  26. var _array = require("../../core/utils/array");
  27. var _array2 = _interopRequireDefault(_array);
  28. var _locker = require("../../core/utils/locker");
  29. var _locker2 = _interopRequireDefault(_locker);
  30. var _ui = require("../../ui/widget/ui.widget");
  31. var _ui2 = _interopRequireDefault(_ui);
  32. var _editor = require("../../ui/editor/editor");
  33. var _editor2 = _interopRequireDefault(_editor);
  34. var _template = require("./template");
  35. var _template2 = _interopRequireDefault(_template);
  36. var _module = require("./module");
  37. var _module2 = _interopRequireDefault(_module);
  38. var _uiCollection_widget = require("../../ui/collection/ui.collection_widget.edit");
  39. var _uiCollection_widget2 = _interopRequireDefault(_uiCollection_widget);
  40. var _data = require("../../core/utils/data");
  41. var _data2 = _interopRequireDefault(_data);
  42. var _extend = require("../../core/utils/extend");
  43. var _extend2 = _interopRequireDefault(_extend);
  44. var _inflector = require("../../core/utils/inflector");
  45. var _inflector2 = _interopRequireDefault(_inflector);
  46. var _errors = require("../../core/errors");
  47. var _errors2 = _interopRequireDefault(_errors);
  48. function _interopRequireDefault(obj) {
  49. return obj && obj.__esModule ? obj : {
  50. "default": obj
  51. }
  52. }
  53. function _typeof(obj) {
  54. "@babel/helpers - typeof";
  55. return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj) {
  56. return typeof obj
  57. } : function(obj) {
  58. return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj
  59. }, _typeof(obj)
  60. }
  61. var each = _iterator2.default.each;
  62. var inArray = _array2.default.inArray;
  63. var compileSetter = _data2.default.compileSetter;
  64. var compileGetter = _data2.default.compileGetter;
  65. var extendFromObject = _extend2.default.extendFromObject;
  66. var ITEM_ALIAS_ATTRIBUTE_NAME = "dxItemAlias";
  67. var SKIP_APPLY_ACTION_CATEGORIES = ["rendering"];
  68. var NG_MODEL_OPTION = "value";
  69. var safeApply = function(func, scope) {
  70. if (scope.$root.$$phase) {
  71. return func(scope)
  72. } else {
  73. return scope.$apply(function() {
  74. return func(scope)
  75. })
  76. }
  77. };
  78. var ComponentBuilder = _class2.default.inherit({
  79. ctor: function(options) {
  80. this._componentDisposing = (0, _callbacks2.default)();
  81. this._optionChangedCallbacks = (0, _callbacks2.default)();
  82. this._ngLocker = new _locker2.default;
  83. this._scope = options.scope;
  84. this._$element = options.$element;
  85. this._$templates = options.$templates;
  86. this._componentClass = options.componentClass;
  87. this._parse = options.parse;
  88. this._compile = options.compile;
  89. this._itemAlias = options.itemAlias;
  90. this._transcludeFn = options.transcludeFn;
  91. this._digestCallbacks = options.dxDigestCallbacks;
  92. this._normalizeOptions(options.ngOptions);
  93. this._initComponentBindings();
  94. this._initComponent(this._scope);
  95. if (!options.ngOptions) {
  96. this._addOptionsStringWatcher(options.ngOptionsString)
  97. }
  98. },
  99. _addOptionsStringWatcher: function(optionsString) {
  100. var _this = this;
  101. var clearOptionsStringWatcher = this._scope.$watch(optionsString, function(newOptions) {
  102. if (!newOptions) {
  103. return
  104. }
  105. clearOptionsStringWatcher();
  106. _this._normalizeOptions(newOptions);
  107. _this._initComponentBindings();
  108. _this._component.option(_this._evalOptions(_this._scope))
  109. });
  110. this._componentDisposing.add(clearOptionsStringWatcher)
  111. },
  112. _normalizeOptions: function(options) {
  113. var _this2 = this;
  114. this._ngOptions = extendFromObject({}, options);
  115. if (!options) {
  116. return
  117. }
  118. if (!Object.prototype.hasOwnProperty.call(options, "bindingOptions") && options.bindingOptions) {
  119. this._ngOptions.bindingOptions = options.bindingOptions
  120. }
  121. if (options.bindingOptions) {
  122. each(options.bindingOptions, function(key, value) {
  123. if ("string" === _type2.default.type(value)) {
  124. _this2._ngOptions.bindingOptions[key] = {
  125. dataPath: value
  126. }
  127. }
  128. })
  129. }
  130. },
  131. _initComponent: function(scope) {
  132. this._component = new this._componentClass(this._$element, this._evalOptions(scope));
  133. this._component._isHidden = true;
  134. this._handleDigestPhase()
  135. },
  136. _handleDigestPhase: function() {
  137. var _this3 = this;
  138. var beginUpdate = function() {
  139. _this3._component.beginUpdate()
  140. };
  141. var endUpdate = function() {
  142. _this3._component.endUpdate()
  143. };
  144. this._digestCallbacks.begin.add(beginUpdate);
  145. this._digestCallbacks.end.add(endUpdate);
  146. this._componentDisposing.add(function() {
  147. _this3._digestCallbacks.begin.remove(beginUpdate);
  148. _this3._digestCallbacks.end.remove(endUpdate)
  149. })
  150. },
  151. _initComponentBindings: function() {
  152. var _this4 = this;
  153. var optionDependencies = {};
  154. if (!this._ngOptions.bindingOptions) {
  155. return
  156. }
  157. each(this._ngOptions.bindingOptions, function(optionPath, value) {
  158. var separatorIndex = optionPath.search(/\[|\./);
  159. var optionForSubscribe = separatorIndex > -1 ? optionPath.substring(0, separatorIndex) : optionPath;
  160. var prevWatchMethod;
  161. var clearWatcher;
  162. var valuePath = value.dataPath;
  163. var deepWatch = true;
  164. var forcePlainWatchMethod = false;
  165. if (void 0 !== value.deep) {
  166. forcePlainWatchMethod = deepWatch = !!value.deep
  167. }
  168. if (!optionDependencies[optionForSubscribe]) {
  169. optionDependencies[optionForSubscribe] = {}
  170. }
  171. optionDependencies[optionForSubscribe][optionPath] = valuePath;
  172. var watchCallback = function(newValue, oldValue) {
  173. if (_this4._ngLocker.locked(optionPath)) {
  174. return
  175. }
  176. _this4._ngLocker.obtain(optionPath);
  177. _this4._component.option(optionPath, newValue);
  178. updateWatcher();
  179. if (_this4._component._optionValuesEqual(optionPath, oldValue, newValue) && _this4._ngLocker.locked(optionPath)) {
  180. _this4._ngLocker.release(optionPath)
  181. }
  182. };
  183. var updateWatcher = function() {
  184. var watchMethod = Array.isArray(_this4._scope.$eval(valuePath)) && !forcePlainWatchMethod ? "$watchCollection" : "$watch";
  185. if (prevWatchMethod !== watchMethod) {
  186. if (clearWatcher) {
  187. clearWatcher()
  188. }
  189. clearWatcher = _this4._scope[watchMethod](valuePath, watchCallback, deepWatch);
  190. prevWatchMethod = watchMethod
  191. }
  192. };
  193. updateWatcher();
  194. _this4._componentDisposing.add(clearWatcher)
  195. });
  196. this._optionChangedCallbacks.add(function(args) {
  197. var optionName = args.name;
  198. var fullName = args.fullName;
  199. var component = args.component;
  200. if (_this4._ngLocker.locked(fullName)) {
  201. _this4._ngLocker.release(fullName);
  202. return
  203. }
  204. if (!optionDependencies || !optionDependencies[optionName]) {
  205. return
  206. }
  207. var isActivePhase = _this4._scope.$root.$$phase;
  208. var obtainOption = function() {
  209. _this4._ngLocker.obtain(fullName)
  210. };
  211. if (isActivePhase) {
  212. _this4._digestCallbacks.begin.add(obtainOption)
  213. } else {
  214. obtainOption()
  215. }
  216. safeApply(function() {
  217. each(optionDependencies[optionName], function(optionPath, valuePath) {
  218. if (!_this4._optionsAreLinked(fullName, optionPath)) {
  219. return
  220. }
  221. var value = component.option(optionPath);
  222. _this4._parse(valuePath).assign(_this4._scope, value);
  223. var scopeValue = _this4._parse(valuePath)(_this4._scope);
  224. if (scopeValue !== value) {
  225. args.component.option(optionPath, scopeValue)
  226. }
  227. })
  228. }, _this4._scope);
  229. var releaseOption = function releaseOption() {
  230. if (_this4._ngLocker.locked(fullName)) {
  231. _this4._ngLocker.release(fullName)
  232. }
  233. _this4._digestCallbacks.begin.remove(obtainOption);
  234. _this4._digestCallbacks.end.remove(releaseOption)
  235. };
  236. if (isActivePhase) {
  237. _this4._digestCallbacks.end.addPrioritized(releaseOption)
  238. } else {
  239. releaseOption()
  240. }
  241. })
  242. },
  243. _optionsAreNested: function(optionPath1, optionPath2) {
  244. var parentSeparator = optionPath1[optionPath2.length];
  245. return 0 === optionPath1.indexOf(optionPath2) && ("." === parentSeparator || "[" === parentSeparator)
  246. },
  247. _optionsAreLinked: function(optionPath1, optionPath2) {
  248. if (optionPath1 === optionPath2) {
  249. return true
  250. }
  251. return optionPath1.length > optionPath2.length ? this._optionsAreNested(optionPath1, optionPath2) : this._optionsAreNested(optionPath2, optionPath1)
  252. },
  253. _compilerByTemplate: function(template) {
  254. var _this5 = this;
  255. var scopeItemsPath = this._getScopeItemsPath();
  256. return function(options) {
  257. var $resultMarkup = (0, _renderer2.default)(template).clone();
  258. var dataIsScope = options.model && options.model.constructor === _this5._scope.$root.constructor;
  259. var templateScope = dataIsScope ? options.model : options.noModel ? _this5._scope : _this5._createScopeWithData(options);
  260. if (scopeItemsPath) {
  261. _this5._synchronizeScopes(templateScope, scopeItemsPath, options.index)
  262. }
  263. $resultMarkup.appendTo(options.container);
  264. if (!options.noModel) {
  265. _events_engine2.default.on($resultMarkup, "$destroy", function() {
  266. var destroyAlreadyCalled = !templateScope.$parent;
  267. if (destroyAlreadyCalled) {
  268. return
  269. }
  270. templateScope.$destroy()
  271. })
  272. }
  273. var ngTemplate = _this5._compile($resultMarkup, _this5._transcludeFn);
  274. _this5._applyAsync(function(scope) {
  275. ngTemplate(scope, null, {
  276. parentBoundTranscludeFn: _this5._transcludeFn
  277. })
  278. }, templateScope);
  279. return $resultMarkup
  280. }
  281. },
  282. _applyAsync: function(func, scope) {
  283. var _this6 = this;
  284. func(scope);
  285. if (!scope.$root.$$phase) {
  286. if (!this._renderingTimer) {
  287. this._renderingTimer = setTimeout(function() {
  288. scope.$apply();
  289. _this6._renderingTimer = null
  290. })
  291. }
  292. this._componentDisposing.add(function() {
  293. clearTimeout(_this6._renderingTimer)
  294. })
  295. }
  296. },
  297. _getScopeItemsPath: function() {
  298. if (this._componentClass.subclassOf(_uiCollection_widget2.default) && this._ngOptions.bindingOptions && this._ngOptions.bindingOptions.items) {
  299. return this._ngOptions.bindingOptions.items.dataPath
  300. }
  301. },
  302. _createScopeWithData: function(options) {
  303. var newScope = this._scope.$new();
  304. if (this._itemAlias) {
  305. newScope[this._itemAlias] = options.model
  306. }
  307. if (_type2.default.isDefined(options.index)) {
  308. newScope.$index = options.index
  309. }
  310. return newScope
  311. },
  312. _synchronizeScopes: function(itemScope, parentPrefix, itemIndex) {
  313. if (this._itemAlias && "object" !== _typeof(itemScope[this._itemAlias])) {
  314. this._synchronizeScopeField({
  315. parentScope: this._scope,
  316. childScope: itemScope,
  317. fieldPath: this._itemAlias,
  318. parentPrefix: parentPrefix,
  319. itemIndex: itemIndex
  320. })
  321. }
  322. },
  323. _synchronizeScopeField: function(args) {
  324. var parentScope = args.parentScope;
  325. var childScope = args.childScope;
  326. var fieldPath = args.fieldPath;
  327. var parentPrefix = args.parentPrefix;
  328. var itemIndex = args.itemIndex;
  329. var innerPathSuffix = fieldPath === this._itemAlias ? "" : "." + fieldPath;
  330. var collectionField = void 0 !== itemIndex;
  331. var optionOuterBag = [parentPrefix];
  332. if (collectionField) {
  333. if (!_type2.default.isNumeric(itemIndex)) {
  334. return
  335. }
  336. optionOuterBag.push("[", itemIndex, "]")
  337. }
  338. optionOuterBag.push(innerPathSuffix);
  339. var optionOuterPath = optionOuterBag.join("");
  340. var clearParentWatcher = parentScope.$watch(optionOuterPath, function(newValue, oldValue) {
  341. if (newValue !== oldValue) {
  342. compileSetter(fieldPath)(childScope, newValue)
  343. }
  344. });
  345. var clearItemWatcher = childScope.$watch(fieldPath, function(newValue, oldValue) {
  346. if (newValue !== oldValue) {
  347. if (collectionField && !compileGetter(parentPrefix)(parentScope)[itemIndex]) {
  348. clearItemWatcher();
  349. return
  350. }
  351. compileSetter(optionOuterPath)(parentScope, newValue)
  352. }
  353. });
  354. this._componentDisposing.add([clearParentWatcher, clearItemWatcher])
  355. },
  356. _evalOptions: function(scope) {
  357. var _this8 = this;
  358. var result = extendFromObject({}, this._ngOptions);
  359. delete result.bindingOptions;
  360. if (this._ngOptions.bindingOptions) {
  361. each(this._ngOptions.bindingOptions, function(key, value) {
  362. result[key] = scope.$eval(value.dataPath)
  363. })
  364. }
  365. result._optionChangedCallbacks = this._optionChangedCallbacks;
  366. result._disposingCallbacks = this._componentDisposing;
  367. result.onActionCreated = function(component, action, config) {
  368. if (config && inArray(config.category, SKIP_APPLY_ACTION_CATEGORIES) > -1) {
  369. return action
  370. }
  371. var wrappedAction = function() {
  372. var _this7 = this;
  373. var args = arguments;
  374. if (!scope || !scope.$root || scope.$root.$$phase) {
  375. return action.apply(this, args)
  376. }
  377. return safeApply(function() {
  378. return action.apply(_this7, args)
  379. }, scope)
  380. };
  381. return wrappedAction
  382. };
  383. result.beforeActionExecute = result.onActionCreated;
  384. result.nestedComponentOptions = function(component) {
  385. return {
  386. templatesRenderAsynchronously: component.option("templatesRenderAsynchronously"),
  387. forceApplyBindings: component.option("forceApplyBindings"),
  388. modelByElement: component.option("modelByElement"),
  389. onActionCreated: component.option("onActionCreated"),
  390. beforeActionExecute: component.option("beforeActionExecute"),
  391. nestedComponentOptions: component.option("nestedComponentOptions")
  392. }
  393. };
  394. result.templatesRenderAsynchronously = true;
  395. if ((0, _config2.default)().wrapActionsBeforeExecute) {
  396. result.forceApplyBindings = function() {
  397. safeApply(function() {}, scope)
  398. }
  399. }
  400. result.integrationOptions = {
  401. createTemplate: function(element) {
  402. return new _template2.default(element, _this8._compilerByTemplate.bind(_this8))
  403. },
  404. watchMethod: function(fn, callback, options) {
  405. options = options || {};
  406. var immediateValue;
  407. var skipCallback = options.skipImmediate;
  408. var disposeWatcher = scope.$watch(function() {
  409. var value = fn();
  410. if (value instanceof Date) {
  411. value = value.valueOf()
  412. }
  413. return value
  414. }, function(newValue) {
  415. var isSameValue = immediateValue === newValue;
  416. if (!skipCallback && (!isSameValue || isSameValue && options.deep)) {
  417. callback(newValue)
  418. }
  419. skipCallback = false
  420. }, options.deep);
  421. if (!skipCallback) {
  422. immediateValue = fn();
  423. callback(immediateValue)
  424. }
  425. if ((0, _config2.default)().wrapActionsBeforeExecute) {
  426. _this8._applyAsync(function() {}, scope)
  427. }
  428. return disposeWatcher
  429. },
  430. templates: {
  431. "dx-polymorph-widget": {
  432. render: function(options) {
  433. var widgetName = options.model.widget;
  434. if (!widgetName) {
  435. return
  436. }
  437. if ("button" === widgetName || "tabs" === widgetName || "dropDownMenu" === widgetName) {
  438. var deprecatedName = widgetName;
  439. widgetName = _inflector2.default.camelize("dx-" + widgetName);
  440. _errors2.default.log("W0001", "dxToolbar - 'widget' item field", deprecatedName, "16.1", "Use: '" + widgetName + "' instead")
  441. }
  442. var markup = (0, _renderer2.default)("<div>").attr(_inflector2.default.dasherize(widgetName), "options").get(0);
  443. var newScope = _this8._scope.$new();
  444. newScope.options = options.model.options;
  445. options.container.append(markup);
  446. _this8._compile(markup)(newScope)
  447. }
  448. }
  449. }
  450. };
  451. result.modelByElement = function() {
  452. return scope
  453. };
  454. return result
  455. }
  456. });
  457. ComponentBuilder = ComponentBuilder.inherit({
  458. ctor: function(options) {
  459. this._componentName = options.componentName;
  460. this._ngModel = options.ngModel;
  461. this._ngModelController = options.ngModelController;
  462. this.callBase.apply(this, arguments)
  463. },
  464. _isNgModelRequired: function() {
  465. return (this._componentClass.subclassOf(_editor2.default) || this._componentClass.prototype instanceof _editor2.default) && this._ngModel
  466. },
  467. _initComponentBindings: function() {
  468. this.callBase.apply(this, arguments);
  469. this._initNgModelBinding()
  470. },
  471. _initNgModelBinding: function() {
  472. var _this9 = this;
  473. if (!this._isNgModelRequired()) {
  474. return
  475. }
  476. var clearNgModelWatcher = this._scope.$watch(this._ngModel, function(newValue, oldValue) {
  477. if (_this9._ngLocker.locked(NG_MODEL_OPTION)) {
  478. return
  479. }
  480. if (newValue === oldValue) {
  481. return
  482. }
  483. _this9._component.option(NG_MODEL_OPTION, newValue)
  484. });
  485. this._optionChangedCallbacks.add(function(args) {
  486. _this9._ngLocker.obtain(NG_MODEL_OPTION);
  487. try {
  488. if (args.name !== NG_MODEL_OPTION) {
  489. return
  490. }
  491. _this9._ngModelController.$setViewValue(args.value)
  492. } finally {
  493. if (_this9._ngLocker.locked(NG_MODEL_OPTION)) {
  494. _this9._ngLocker.release(NG_MODEL_OPTION)
  495. }
  496. }
  497. });
  498. this._componentDisposing.add(clearNgModelWatcher)
  499. },
  500. _evalOptions: function() {
  501. if (!this._isNgModelRequired()) {
  502. return this.callBase.apply(this, arguments)
  503. }
  504. var result = this.callBase.apply(this, arguments);
  505. result[NG_MODEL_OPTION] = this._parse(this._ngModel)(this._scope);
  506. return result
  507. }
  508. });
  509. var registeredComponents = {};
  510. var registerComponentDirective = function(name) {
  511. var priority = "dxValidator" !== name ? 1 : 10;
  512. _module2.default.directive(name, ["$compile", "$parse", "dxDigestCallbacks", function($compile, $parse, dxDigestCallbacks) {
  513. return {
  514. restrict: "A",
  515. require: "^?ngModel",
  516. priority: priority,
  517. compile: function($element) {
  518. var componentClass = registeredComponents[name];
  519. var $content = componentClass.subclassOf(_ui2.default) ? $element.contents().detach() : null;
  520. return function(scope, $element, attrs, ngModelController, transcludeFn) {
  521. $element.append($content);
  522. safeApply(function() {
  523. new ComponentBuilder({
  524. componentClass: componentClass,
  525. componentName: name,
  526. compile: $compile,
  527. parse: $parse,
  528. $element: $element,
  529. scope: scope,
  530. ngOptionsString: attrs[name],
  531. ngOptions: attrs[name] ? scope.$eval(attrs[name]) : {},
  532. ngModel: attrs.ngModel,
  533. ngModelController: ngModelController,
  534. transcludeFn: transcludeFn,
  535. itemAlias: attrs[ITEM_ALIAS_ATTRIBUTE_NAME],
  536. dxDigestCallbacks: dxDigestCallbacks
  537. })
  538. }, scope)
  539. }
  540. }
  541. }
  542. }])
  543. };
  544. _component_registrator_callbacks2.default.add(function(name, componentClass) {
  545. if (!registeredComponents[name]) {
  546. registerComponentDirective(name)
  547. }
  548. registeredComponents[name] = componentClass
  549. });