@ui5/webcomponents-base 2.0.0-rc.6 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +1 -4
- package/dist/.tsbuildinfo +1 -1
- package/dist/UI5Element.d.ts +9 -8
- package/dist/UI5Element.js +111 -108
- package/dist/UI5Element.js.map +1 -1
- package/dist/UI5ElementMetadata.d.ts +6 -15
- package/dist/UI5ElementMetadata.js +3 -71
- package/dist/UI5ElementMetadata.js.map +1 -1
- package/dist/asset-registries/Icons.d.ts +1 -1
- package/dist/asset-registries/Icons.js.map +1 -1
- package/dist/converters/DOMReference.d.ts +5 -0
- package/dist/converters/DOMReference.js +13 -0
- package/dist/converters/DOMReference.js.map +1 -0
- package/dist/custom-elements-internal.json +15 -275
- package/dist/custom-elements.json +15 -269
- package/dist/decorators/property.js +1 -1
- package/dist/decorators/property.js.map +1 -1
- package/dist/delegate/ItemNavigation.d.ts +1 -1
- package/dist/delegate/ItemNavigation.js.map +1 -1
- package/dist/features/InputElementsFormSupport.d.ts +1 -1
- package/dist/features/InputElementsFormSupport.js.map +1 -1
- package/dist/features/OpenUI5Support.js +3 -0
- package/dist/features/OpenUI5Support.js.map +1 -1
- package/dist/generated/VersionInfo.js +4 -4
- package/dist/generated/VersionInfo.js.map +1 -1
- package/dist/prod/UI5Element.js +1 -1
- package/dist/prod/UI5Element.js.map +3 -3
- package/dist/prod/UI5ElementMetadata.js +1 -1
- package/dist/prod/UI5ElementMetadata.js.map +3 -3
- package/dist/prod/asset-registries/Icons.js +1 -1
- package/dist/prod/asset-registries/Icons.js.map +2 -2
- package/dist/prod/converters/DOMReference.js +2 -0
- package/dist/prod/converters/DOMReference.js.map +7 -0
- package/dist/prod/decorators/property.js +1 -1
- package/dist/prod/decorators/property.js.map +2 -2
- package/dist/prod/delegate/ItemNavigation.js.map +1 -1
- package/dist/prod/features/InputElementsFormSupport.js.map +1 -1
- package/dist/prod/features/OpenUI5Support.js +1 -1
- package/dist/prod/features/OpenUI5Support.js.map +2 -2
- package/dist/prod/generated/VersionInfo.js +1 -1
- package/dist/prod/generated/VersionInfo.js.map +2 -2
- package/dist/prod/util/AriaLabelHelper.js.map +1 -1
- package/dist/util/AriaLabelHelper.js.map +1 -1
- package/dist/util/getClassCopy.d.ts +5 -2
- package/package.json +3 -3
- package/dist/prod/types/CSSColor.js +0 -2
- package/dist/prod/types/CSSColor.js.map +0 -7
- package/dist/prod/types/CSSSize.js +0 -2
- package/dist/prod/types/CSSSize.js.map +0 -7
- package/dist/prod/types/DOMReference.js +0 -2
- package/dist/prod/types/DOMReference.js.map +0 -7
- package/dist/prod/types/DataType.js +0 -2
- package/dist/prod/types/DataType.js.map +0 -7
- package/dist/prod/types/Float.js +0 -2
- package/dist/prod/types/Float.js.map +0 -7
- package/dist/prod/types/Integer.js +0 -2
- package/dist/prod/types/Integer.js.map +0 -7
- package/dist/types/CSSColor.d.ts +0 -11
- package/dist/types/CSSColor.js +0 -14
- package/dist/types/CSSColor.js.map +0 -1
- package/dist/types/CSSSize.d.ts +0 -11
- package/dist/types/CSSSize.js +0 -14
- package/dist/types/CSSSize.js.map +0 -1
- package/dist/types/DOMReference.d.ts +0 -13
- package/dist/types/DOMReference.js +0 -21
- package/dist/types/DOMReference.js.map +0 -1
- package/dist/types/DataType.d.ts +0 -20
- package/dist/types/DataType.js +0 -39
- package/dist/types/DataType.js.map +0 -1
- package/dist/types/Float.d.ts +0 -14
- package/dist/types/Float.js +0 -18
- package/dist/types/Float.js.map +0 -1
- package/dist/types/Integer.d.ts +0 -14
- package/dist/types/Integer.js +0 -18
- package/dist/types/Integer.js.map +0 -1
package/dist/UI5Element.d.ts
CHANGED
|
@@ -54,7 +54,14 @@ declare abstract class UI5Element extends HTMLElement {
|
|
|
54
54
|
static template?: TemplateFunction;
|
|
55
55
|
static _metadata: UI5ElementMetadata;
|
|
56
56
|
static renderer: Renderer;
|
|
57
|
+
initializedProperties: Map<string, unknown>;
|
|
58
|
+
_rendered: boolean;
|
|
57
59
|
constructor();
|
|
60
|
+
_initShadowRoot(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Note: this "slotchange" listener is for slots, rendered in the component's shadow root
|
|
63
|
+
*/
|
|
64
|
+
_onShadowRootSlotChange(e: Event): void;
|
|
58
65
|
/**
|
|
59
66
|
* Returns a unique ID for this UI5 Element
|
|
60
67
|
*
|
|
@@ -148,14 +155,6 @@ declare abstract class UI5Element extends HTMLElement {
|
|
|
148
155
|
* @private
|
|
149
156
|
*/
|
|
150
157
|
_updateAttribute(name: string, newValue: PropertyValue): void;
|
|
151
|
-
/**
|
|
152
|
-
* @private
|
|
153
|
-
*/
|
|
154
|
-
_upgradeProperty(this: Record<string, any>, propertyName: string): void;
|
|
155
|
-
/**
|
|
156
|
-
* @private
|
|
157
|
-
*/
|
|
158
|
-
_upgradeAllProperties(): void;
|
|
159
158
|
/**
|
|
160
159
|
* Returns a singleton event listener for the "change" event of a child in a given slot
|
|
161
160
|
*
|
|
@@ -180,6 +179,7 @@ declare abstract class UI5Element extends HTMLElement {
|
|
|
180
179
|
_detachSlotChange(child: HTMLSlotElement, slotName: string): void;
|
|
181
180
|
/**
|
|
182
181
|
* Whenever a slot element is slotted inside a UI5 Web Component, its slotchange event invalidates the component
|
|
182
|
+
* Note: this "slotchange" listener is for slots that are children of the component (in the light dom, as opposed to slots rendered by the component in the shadow root)
|
|
183
183
|
*
|
|
184
184
|
* @param slotName the name of the slot, where the slot element (whose slotchange event we're listening to) is
|
|
185
185
|
* @private
|
|
@@ -213,6 +213,7 @@ declare abstract class UI5Element extends HTMLElement {
|
|
|
213
213
|
* @public
|
|
214
214
|
*/
|
|
215
215
|
onInvalidation(changeInfo: ChangeInfo): void;
|
|
216
|
+
updateAttributes(): void;
|
|
216
217
|
/**
|
|
217
218
|
* Do not call this method directly, only intended to be called by js
|
|
218
219
|
* @protected
|
package/dist/UI5Element.js
CHANGED
|
@@ -22,6 +22,31 @@ const DEV_MODE = true;
|
|
|
22
22
|
let autoId = 0;
|
|
23
23
|
const elementTimeouts = new Map();
|
|
24
24
|
const uniqueDependenciesCache = new Map();
|
|
25
|
+
const defaultConverter = {
|
|
26
|
+
fromAttribute(value, type) {
|
|
27
|
+
if (type === Boolean) {
|
|
28
|
+
return value !== null;
|
|
29
|
+
}
|
|
30
|
+
if (type === Number) {
|
|
31
|
+
return value === null ? undefined : parseFloat(value);
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
},
|
|
35
|
+
toAttribute(value, type) {
|
|
36
|
+
if (type === Boolean) {
|
|
37
|
+
return value ? "" : null;
|
|
38
|
+
}
|
|
39
|
+
// don't set attributes for arrays and objects
|
|
40
|
+
if (type === Object || type === Array) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// object, array, other
|
|
44
|
+
if (value === null || value === undefined) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return String(value);
|
|
48
|
+
},
|
|
49
|
+
};
|
|
25
50
|
/**
|
|
26
51
|
* Triggers re-rendering of a UI5Element instance due to state change.
|
|
27
52
|
* @param {ChangeInfo} changeInfo An object with information about the change that caused invalidation.
|
|
@@ -65,6 +90,10 @@ function getPropertyDescriptor(proto, name) {
|
|
|
65
90
|
class UI5Element extends HTMLElement {
|
|
66
91
|
constructor() {
|
|
67
92
|
super();
|
|
93
|
+
// used to differentiate whether a setter is called from the constructor (from an initializer) or later
|
|
94
|
+
// setters from the constructor should not set attributes, this is delegated after the first rendering but is async
|
|
95
|
+
// setters after the constructor can set attributes synchronously for more convinient development
|
|
96
|
+
this._rendered = false;
|
|
68
97
|
const ctor = this.constructor;
|
|
69
98
|
this._changedState = []; // Filled on each invalidation, cleared on re-render (used for debugging)
|
|
70
99
|
this._suppressInvalidation = true; // A flag telling whether all invalidations should be ignored. Initialized with "true" because a UI5Element can not be invalidated until it is rendered for the first time
|
|
@@ -82,10 +111,35 @@ class UI5Element extends HTMLElement {
|
|
|
82
111
|
this._doNotSyncAttributes = new Set(); // attributes that are excluded from attributeChangedCallback synchronization
|
|
83
112
|
this._slotsAssignedNodes = new WeakMap(); // map of all nodes, slotted (directly or transitively) per component slot
|
|
84
113
|
this._state = { ...ctor.getMetadata().getInitialState() };
|
|
85
|
-
|
|
114
|
+
// save properties set before element is upgraded, as they will be overriden by the field initializers in the constructor
|
|
115
|
+
this.initializedProperties = new Map();
|
|
116
|
+
const allProps = this.constructor.getMetadata().getPropertiesList();
|
|
117
|
+
allProps.forEach(propertyName => {
|
|
118
|
+
if (this.hasOwnProperty(propertyName)) { // eslint-disable-line
|
|
119
|
+
const value = this[propertyName];
|
|
120
|
+
this.initializedProperties.set(propertyName, value);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
this._initShadowRoot();
|
|
124
|
+
}
|
|
125
|
+
_initShadowRoot() {
|
|
126
|
+
const ctor = this.constructor;
|
|
86
127
|
if (ctor._needsShadowDOM()) {
|
|
87
128
|
const defaultOptions = { mode: "open" };
|
|
88
129
|
this.attachShadow({ ...defaultOptions, ...ctor.getMetadata().getShadowRootOptions() });
|
|
130
|
+
const slotsAreManaged = ctor.getMetadata().slotsAreManaged();
|
|
131
|
+
if (slotsAreManaged) {
|
|
132
|
+
this.shadowRoot.addEventListener("slotchange", this._onShadowRootSlotChange.bind(this));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Note: this "slotchange" listener is for slots, rendered in the component's shadow root
|
|
138
|
+
*/
|
|
139
|
+
_onShadowRootSlotChange(e) {
|
|
140
|
+
const targetShadowRoot = e.target?.getRootNode(); // the "slotchange" event target is always a slot element
|
|
141
|
+
if (targetShadowRoot === this.shadowRoot) { // only for slotchange events that originate from slots, belonging to the component's shadow root
|
|
142
|
+
this._processChildren();
|
|
89
143
|
}
|
|
90
144
|
}
|
|
91
145
|
/**
|
|
@@ -124,7 +178,8 @@ class UI5Element extends HTMLElement {
|
|
|
124
178
|
if (DEV_MODE) {
|
|
125
179
|
const props = this.constructor.getMetadata().getProperties();
|
|
126
180
|
for (const [prop, propData] of Object.entries(props)) { // eslint-disable-line
|
|
127
|
-
if (Object.hasOwn(this, prop)) {
|
|
181
|
+
if (Object.hasOwn(this, prop) && !this.initializedProperties.has(prop)) {
|
|
182
|
+
// initialized properties should not trigger this error as they will be reassigned, only property initializers will trigger this in case unsupported TS mode
|
|
128
183
|
// eslint-disable-next-line no-console
|
|
129
184
|
console.error(`[UI5-FWK] ${this.constructor.getMetadata().getTag()} has a property [${prop}] that is shadowed by the instance. Updates to this property will not invalidate the component. Possible reason is TS target ES2022 or TS useDefineForClassFields`);
|
|
130
185
|
}
|
|
@@ -199,10 +254,9 @@ class UI5Element extends HTMLElement {
|
|
|
199
254
|
return;
|
|
200
255
|
}
|
|
201
256
|
const canSlotText = metadata.canSlotText();
|
|
202
|
-
const hasClonedSlot = Object.keys(metadata.getSlots()).some(slotName => metadata.getSlots()[slotName].cloned);
|
|
203
257
|
const mutationObserverOptions = {
|
|
204
258
|
childList: true,
|
|
205
|
-
subtree: canSlotText
|
|
259
|
+
subtree: canSlotText,
|
|
206
260
|
characterData: canSlotText,
|
|
207
261
|
};
|
|
208
262
|
observeDOMNode(this, this._processChildren.bind(this), mutationObserverOptions);
|
|
@@ -301,6 +355,7 @@ class UI5Element extends HTMLElement {
|
|
|
301
355
|
// not the order elements are defined.
|
|
302
356
|
slottedChildrenMap.forEach((children, propertyName) => {
|
|
303
357
|
this._state[propertyName] = children.sort((a, b) => a.idx - b.idx).map(_ => _.child);
|
|
358
|
+
this._state[kebabToCamelCase(propertyName)] = this._state[propertyName];
|
|
304
359
|
});
|
|
305
360
|
// Compare the content of each slot with the cached values and invalidate for the ones that changed
|
|
306
361
|
let invalidated = false;
|
|
@@ -345,6 +400,7 @@ class UI5Element extends HTMLElement {
|
|
|
345
400
|
}
|
|
346
401
|
});
|
|
347
402
|
this._state[propertyName] = [];
|
|
403
|
+
this._state[kebabToCamelCase(propertyName)] = this._state[propertyName];
|
|
348
404
|
}
|
|
349
405
|
/**
|
|
350
406
|
* Attach a callback that will be executed whenever the component is invalidated
|
|
@@ -398,20 +454,8 @@ class UI5Element extends HTMLElement {
|
|
|
398
454
|
const nameInCamelCase = kebabToCamelCase(realName);
|
|
399
455
|
if (properties.hasOwnProperty(nameInCamelCase)) { // eslint-disable-line
|
|
400
456
|
const propData = properties[nameInCamelCase];
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
if (propertyType && propertyType.isDataTypeClass) {
|
|
404
|
-
propertyValidator = propertyType;
|
|
405
|
-
}
|
|
406
|
-
if (propertyValidator) {
|
|
407
|
-
newPropertyValue = propertyValidator.attributeToProperty(newValue);
|
|
408
|
-
}
|
|
409
|
-
else if (propertyType === Boolean) {
|
|
410
|
-
newPropertyValue = newValue !== null;
|
|
411
|
-
}
|
|
412
|
-
else {
|
|
413
|
-
newPropertyValue = newValue;
|
|
414
|
-
}
|
|
457
|
+
const converter = propData.converter ?? defaultConverter;
|
|
458
|
+
newPropertyValue = converter.fromAttribute(newValue, propData.type);
|
|
415
459
|
this[nameInCamelCase] = newPropertyValue;
|
|
416
460
|
}
|
|
417
461
|
}
|
|
@@ -435,55 +479,29 @@ class UI5Element extends HTMLElement {
|
|
|
435
479
|
}
|
|
436
480
|
const properties = ctor.getMetadata().getProperties();
|
|
437
481
|
const propData = properties[name];
|
|
438
|
-
const propertyType = propData.type;
|
|
439
|
-
let propertyValidator = propData.validator;
|
|
440
482
|
const attrName = camelToKebabCase(name);
|
|
441
|
-
const
|
|
442
|
-
if (
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
if (newAttrValue === null) { // null means there must be no attribute for the current value of the property
|
|
448
|
-
this._doNotSyncAttributes.add(attrName); // skip the attributeChangedCallback call for this attribute
|
|
449
|
-
this.removeAttribute(attrName); // remove the attribute safely (will not trigger synchronization to the property value due to the above line)
|
|
450
|
-
this._doNotSyncAttributes.delete(attrName); // enable synchronization again for this attribute
|
|
483
|
+
const converter = propData.converter || defaultConverter;
|
|
484
|
+
if (DEV_MODE) {
|
|
485
|
+
const tag = this.constructor.getMetadata().getTag();
|
|
486
|
+
if (typeof newValue === "boolean" && propData.type !== Boolean) {
|
|
487
|
+
// eslint-disable-next-line
|
|
488
|
+
console.error(`[UI5-FWK] boolean value for property [${name}] of component [${tag}] is missing "{ type: Boolean }" in its property decorator. Attribute conversion will treat it as a string. If this is intended, pass the value converted to string, otherwise add the type to the property decorator`);
|
|
451
489
|
}
|
|
452
|
-
|
|
453
|
-
|
|
490
|
+
if (typeof newValue === "number" && propData.type !== Number) {
|
|
491
|
+
// eslint-disable-next-line
|
|
492
|
+
console.error(`[UI5-FWK] numeric value for property [${name}] of component [${tag}] is missing "{ type: Number }" in its property decorator. Attribute conversion will treat it as a string. If this is intended, pass the value converted to string, otherwise add the type to the property decorator`);
|
|
454
493
|
}
|
|
455
494
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
this.removeAttribute(attrName);
|
|
462
|
-
}
|
|
495
|
+
const newAttrValue = converter.toAttribute(newValue, propData.type);
|
|
496
|
+
if (newAttrValue === null || newAttrValue === undefined) { // null means there must be no attribute for the current value of the property
|
|
497
|
+
this._doNotSyncAttributes.add(attrName); // skip the attributeChangedCallback call for this attribute
|
|
498
|
+
this.removeAttribute(attrName); // remove the attribute safely (will not trigger synchronization to the property value due to the above line)
|
|
499
|
+
this._doNotSyncAttributes.delete(attrName); // enable synchronization again for this attribute
|
|
463
500
|
}
|
|
464
|
-
else
|
|
465
|
-
|
|
466
|
-
this.setAttribute(attrName, newValue);
|
|
467
|
-
}
|
|
468
|
-
} // else { return; } // old object handling
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* @private
|
|
472
|
-
*/
|
|
473
|
-
_upgradeProperty(propertyName) {
|
|
474
|
-
if (this.hasOwnProperty(propertyName)) { // eslint-disable-line
|
|
475
|
-
const value = this[propertyName];
|
|
476
|
-
delete this[propertyName];
|
|
477
|
-
this[propertyName] = value;
|
|
501
|
+
else {
|
|
502
|
+
this.setAttribute(attrName, newAttrValue);
|
|
478
503
|
}
|
|
479
504
|
}
|
|
480
|
-
/**
|
|
481
|
-
* @private
|
|
482
|
-
*/
|
|
483
|
-
_upgradeAllProperties() {
|
|
484
|
-
const allProps = this.constructor.getMetadata().getPropertiesList();
|
|
485
|
-
allProps.forEach(this._upgradeProperty.bind(this));
|
|
486
|
-
}
|
|
487
505
|
/**
|
|
488
506
|
* Returns a singleton event listener for the "change" event of a child in a given slot
|
|
489
507
|
*
|
|
@@ -546,6 +564,7 @@ class UI5Element extends HTMLElement {
|
|
|
546
564
|
}
|
|
547
565
|
/**
|
|
548
566
|
* Whenever a slot element is slotted inside a UI5 Web Component, its slotchange event invalidates the component
|
|
567
|
+
* Note: this "slotchange" listener is for slots that are children of the component (in the light dom, as opposed to slots rendered by the component in the shadow root)
|
|
549
568
|
*
|
|
550
569
|
* @param slotName the name of the slot, where the slot element (whose slotchange event we're listening to) is
|
|
551
570
|
* @private
|
|
@@ -585,6 +604,13 @@ class UI5Element extends HTMLElement {
|
|
|
585
604
|
* @public
|
|
586
605
|
*/
|
|
587
606
|
onInvalidation(changeInfo) { } // eslint-disable-line
|
|
607
|
+
updateAttributes() {
|
|
608
|
+
const ctor = this.constructor;
|
|
609
|
+
const props = ctor.getMetadata().getProperties();
|
|
610
|
+
for (const [prop, propData] of Object.entries(props)) { // eslint-disable-line
|
|
611
|
+
this._updateAttribute(prop, this[prop]);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
588
614
|
/**
|
|
589
615
|
* Do not call this method directly, only intended to be called by js
|
|
590
616
|
* @protected
|
|
@@ -592,9 +618,21 @@ class UI5Element extends HTMLElement {
|
|
|
592
618
|
_render() {
|
|
593
619
|
const ctor = this.constructor;
|
|
594
620
|
const hasIndividualSlots = ctor.getMetadata().hasIndividualSlots();
|
|
621
|
+
// restore properties that were initialized before `define` by calling the setter
|
|
622
|
+
if (this.initializedProperties.size > 0) {
|
|
623
|
+
Array.from(this.initializedProperties.entries()).forEach(([prop, value]) => {
|
|
624
|
+
delete this[prop];
|
|
625
|
+
this[prop] = value;
|
|
626
|
+
});
|
|
627
|
+
this.initializedProperties.clear();
|
|
628
|
+
}
|
|
595
629
|
// suppress invalidation to prevent state changes scheduling another rendering
|
|
596
630
|
this._suppressInvalidation = true;
|
|
597
631
|
this.onBeforeRendering();
|
|
632
|
+
if (!this._rendered) {
|
|
633
|
+
// first time rendering, previous setters might have been initializers from the constructor - update attributes here
|
|
634
|
+
this.updateAttributes();
|
|
635
|
+
}
|
|
598
636
|
// Intended for framework usage only. Currently ItemNavigation updates tab indexes after the component has updated its state but before the template is rendered
|
|
599
637
|
this._componentStateFinalizedEventProvider.fireEvent("componentStateFinalized");
|
|
600
638
|
// resume normal invalidation handling
|
|
@@ -625,6 +663,7 @@ class UI5Element extends HTMLElement {
|
|
|
625
663
|
if (ctor._needsShadowDOM()) {
|
|
626
664
|
updateShadowRoot(this);
|
|
627
665
|
}
|
|
666
|
+
this._rendered = true;
|
|
628
667
|
// Safari requires that children get the slot attribute only after the slot tags have been rendered in the shadow DOM
|
|
629
668
|
if (hasIndividualSlots) {
|
|
630
669
|
this._assignIndividualSlotsToChildren();
|
|
@@ -822,18 +861,6 @@ class UI5Element extends HTMLElement {
|
|
|
822
861
|
if (!isValidPropertyName(prop)) {
|
|
823
862
|
console.warn(`"${prop}" is not a valid property name. Use a name that does not collide with DOM APIs`); /* eslint-disable-line */
|
|
824
863
|
}
|
|
825
|
-
if (propData.type === Boolean && propData.defaultValue) {
|
|
826
|
-
throw new Error(`Cannot set a default value for property "${prop}". All booleans are false by default.`);
|
|
827
|
-
}
|
|
828
|
-
if (propData.type === Array) {
|
|
829
|
-
throw new Error(`Wrong type for property "${prop}". Properties cannot be of type Array - use "multiple: true" and set "type" to the single value type, such as "String", "Object", etc...`);
|
|
830
|
-
}
|
|
831
|
-
if (propData.type === Object && propData.defaultValue) {
|
|
832
|
-
throw new Error(`Cannot set a default value for property "${prop}". All properties of type "Object" are empty objects by default.`);
|
|
833
|
-
}
|
|
834
|
-
if (propData.multiple && propData.defaultValue) {
|
|
835
|
-
throw new Error(`Cannot set a default value for property "${prop}". All multiple properties are empty arrays by default.`);
|
|
836
|
-
}
|
|
837
864
|
const descriptor = getPropertyDescriptor(proto, prop);
|
|
838
865
|
// if the decorator is on a setter, proxy the new setter to it
|
|
839
866
|
let origSet;
|
|
@@ -853,43 +880,12 @@ class UI5Element extends HTMLElement {
|
|
|
853
880
|
if (origGet) {
|
|
854
881
|
return origGet.call(this);
|
|
855
882
|
}
|
|
856
|
-
|
|
857
|
-
return this._state[prop];
|
|
858
|
-
}
|
|
859
|
-
const propDefaultValue = propData.defaultValue;
|
|
860
|
-
if (propData.type === Boolean) {
|
|
861
|
-
return false;
|
|
862
|
-
}
|
|
863
|
-
else if (propData.type === String) { // eslint-disable-line
|
|
864
|
-
return propDefaultValue;
|
|
865
|
-
}
|
|
866
|
-
else if (propData.multiple) { // eslint-disable-line
|
|
867
|
-
return [];
|
|
868
|
-
}
|
|
869
|
-
else {
|
|
870
|
-
return propDefaultValue;
|
|
871
|
-
}
|
|
883
|
+
return this._state[prop];
|
|
872
884
|
},
|
|
873
885
|
set(value) {
|
|
874
|
-
let isDifferent;
|
|
875
886
|
const ctor = this.constructor;
|
|
876
|
-
const metadataCtor = ctor.getMetadata().constructor;
|
|
877
|
-
value = metadataCtor.validatePropertyValue(value, propData);
|
|
878
|
-
const propertyType = propData.type;
|
|
879
|
-
let propertyValidator = propData.validator;
|
|
880
887
|
const oldState = origGet ? origGet.call(this) : this._state[prop];
|
|
881
|
-
|
|
882
|
-
propertyValidator = propertyType;
|
|
883
|
-
}
|
|
884
|
-
if (propertyValidator) {
|
|
885
|
-
isDifferent = !propertyValidator.valuesAreEqual(oldState, value);
|
|
886
|
-
}
|
|
887
|
-
else if (Array.isArray(oldState) && Array.isArray(value) && propData.multiple && propData.compareValues) { // compareValues is added for IE, test if needed now
|
|
888
|
-
isDifferent = !arraysAreEqual(oldState, value);
|
|
889
|
-
}
|
|
890
|
-
else {
|
|
891
|
-
isDifferent = oldState !== value;
|
|
892
|
-
}
|
|
888
|
+
const isDifferent = oldState !== value;
|
|
893
889
|
if (isDifferent) {
|
|
894
890
|
// if the decorator is on a setter, use it for storage
|
|
895
891
|
if (origSet) {
|
|
@@ -904,10 +900,13 @@ class UI5Element extends HTMLElement {
|
|
|
904
900
|
newValue: value,
|
|
905
901
|
oldValue: oldState,
|
|
906
902
|
});
|
|
903
|
+
if (this._rendered) {
|
|
904
|
+
// is already rendered so it is not the constructor - can set the attribute synchronously
|
|
905
|
+
this._updateAttribute(prop, value);
|
|
906
|
+
}
|
|
907
907
|
if (ctor.getMetadata().isFormAssociated()) {
|
|
908
908
|
setFormValue(this);
|
|
909
909
|
}
|
|
910
|
-
this._updateAttribute(prop, value);
|
|
911
910
|
}
|
|
912
911
|
},
|
|
913
912
|
});
|
|
@@ -920,7 +919,7 @@ class UI5Element extends HTMLElement {
|
|
|
920
919
|
console.warn(`"${slotName}" is not a valid property name. Use a name that does not collide with DOM APIs`); /* eslint-disable-line */
|
|
921
920
|
}
|
|
922
921
|
const propertyName = slotData.propertyName || slotName;
|
|
923
|
-
|
|
922
|
+
const propertyDescriptor = {
|
|
924
923
|
get() {
|
|
925
924
|
if (this._state[propertyName] !== undefined) {
|
|
926
925
|
return this._state[propertyName];
|
|
@@ -930,7 +929,11 @@ class UI5Element extends HTMLElement {
|
|
|
930
929
|
set() {
|
|
931
930
|
throw new Error("Cannot set slot content directly, use the DOM APIs (appendChild, removeChild, etc...)");
|
|
932
931
|
},
|
|
933
|
-
}
|
|
932
|
+
};
|
|
933
|
+
Object.defineProperty(proto, propertyName, propertyDescriptor);
|
|
934
|
+
if (propertyName !== kebabToCamelCase(propertyName)) {
|
|
935
|
+
Object.defineProperty(proto, kebabToCamelCase(propertyName), propertyDescriptor);
|
|
936
|
+
}
|
|
934
937
|
}
|
|
935
938
|
}
|
|
936
939
|
}
|