aloha-vue 2.80.1 → 2.82.0

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.
Files changed (41) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/aloha-vue.css +7 -0
  3. package/dist/aloha-vue.css.map +1 -1
  4. package/dist/aloha-vue.es.js +361 -24
  5. package/dist/aloha-vue.umd.js +17 -17
  6. package/package.json +1 -1
  7. package/scss/components/AMenu.scss +634 -627
  8. package/src/AMenu/AMenu.js +592 -581
  9. package/src/AMenu/__tests__/AMenu.test.js +54 -0
  10. package/src/AMenu/compositionAPI/SearchAPI.js +45 -2
  11. package/src/AMenu/compositionAPI/__tests__/SearchAPI.test.js +108 -0
  12. package/src/ui/ACheckbox/ACheckbox.js +6 -0
  13. package/src/ui/ACheckbox/ACheckboxItem/ACheckboxItem.js +6 -0
  14. package/src/ui/ADatepicker/ADatepicker.js +6 -0
  15. package/src/ui/ADatepickerRange/ADatepickerRange.js +6 -1
  16. package/src/ui/AFieldset/AFieldset.js +7 -1
  17. package/src/ui/AForm/AForm.js +6 -0
  18. package/src/ui/AFormElement/AFormElement.js +5 -0
  19. package/src/ui/AFormReadonly/AFormReadonly.js +1 -1
  20. package/src/ui/AGroup/AGroup.js +8 -1
  21. package/src/ui/AInput/AInput.js +6 -0
  22. package/src/ui/AInputCurrency/AInputCurrency.js +6 -0
  23. package/src/ui/AInputFile/AInputFile.js +40 -5
  24. package/src/ui/AInputNumber/AInputNumber.js +6 -0
  25. package/src/ui/AInputNumberRange/AInputNumberRange.js +6 -1
  26. package/src/ui/AJson/AJson.js +6 -0
  27. package/src/ui/AMultiselectOrdered/AMultiselectOrdered.js +30 -24
  28. package/src/ui/AOneCheckbox/AOneCheckbox.js +6 -0
  29. package/src/ui/ARadio/ARadio.js +6 -0
  30. package/src/ui/ARadio/ARadioItem/ARadioItem.js +6 -0
  31. package/src/ui/ARouterLinkConfig/ARouterLinkConfig.js +7 -0
  32. package/src/ui/ASelect/ASelect.js +6 -0
  33. package/src/ui/ASelectIcon/ASelectIcon.js +16 -11
  34. package/src/ui/ASelectStyle/ASelectStyle.js +16 -11
  35. package/src/ui/ASlider/ASlider.js +6 -0
  36. package/src/ui/ASwitch/ASwitch.js +11 -5
  37. package/src/ui/ATemplate/ATemplate.js +7 -2
  38. package/src/ui/ATextarea/ATextarea.js +6 -0
  39. package/src/ui/AValidatedJson/AValidatedJson.js +10 -2
  40. package/src/ui/AValidatedJson/AValidatedJsonItem/AValidatedJsonItem.js +6 -0
  41. package/src/ui/__tests__/ReadonlyValueParentClass.test.js +217 -0
@@ -0,0 +1,54 @@
1
+ import {
2
+ nextTick,
3
+ ref,
4
+ } from "vue";
5
+ import {
6
+ describe,
7
+ expect,
8
+ it,
9
+ } from "vitest";
10
+ import {
11
+ shallowMount,
12
+ } from "@vue/test-utils";
13
+
14
+ import AMenu from "../AMenu";
15
+
16
+ describe("AMenu inline placement", () => {
17
+ it("opts into inline placement without changing the default", async() => {
18
+ const wrapper = shallowMount(AMenu, {
19
+ props: {
20
+ canChangeBodyClass: false,
21
+ useBackdropMobile: false,
22
+ },
23
+ global: {
24
+ stubs: {
25
+ AButton: {
26
+ inheritAttrs: false,
27
+ template: "<button />",
28
+ },
29
+ },
30
+ config: {
31
+ globalProperties: {
32
+ $router: {
33
+ currentRoute: ref({ fullPath: "/" }),
34
+ },
35
+ },
36
+ },
37
+ },
38
+ });
39
+ await nextTick();
40
+
41
+ expect(wrapper.vm.searchInDom).toBe(false);
42
+ expect(wrapper.element.tagName).toBe("NAV");
43
+ expect(wrapper.classes()).not.toContain("a_menu_inline");
44
+
45
+ await wrapper.setProps({ isInline: true });
46
+ expect(wrapper.classes()).toContain("a_menu_inline");
47
+ expect(wrapper.classes()).toContain("a_menu_open");
48
+ expect(document.body.classList.contains("a_menu__wrapper_open")).toBe(false);
49
+
50
+ await wrapper.setProps({ isInline: false });
51
+ expect(wrapper.classes()).not.toContain("a_menu_inline");
52
+ wrapper.unmount();
53
+ });
54
+ });
@@ -5,17 +5,28 @@ import {
5
5
  } from "vue";
6
6
 
7
7
  import {
8
+ getElementId,
9
+ } from "../utils/utils";
10
+
11
+ import AKeyBreadcrumbs from "../const/AKeyBreadcrumbs";
12
+ import {
13
+ AKeyId,
8
14
  AKeyLabel,
9
15
  } from "../../const/AKeys";
16
+ import {
17
+ isBrowser,
18
+ } from "../../utils/isBrowser";
10
19
  import {
11
20
  escapeRegExp,
12
21
  forEach,
22
+ map,
13
23
  } from "lodash-es";
14
24
 
15
25
  export default function SearchAPI(props, {
16
26
  dataKeyById = computed(() => ({})),
17
27
  }) {
18
28
  const menuId = toRef(props, "menuId");
29
+ const searchInDom = toRef(props, "searchInDom");
19
30
 
20
31
  const modelSearch = ref("");
21
32
 
@@ -47,15 +58,47 @@ export default function SearchAPI(props, {
47
58
  return escapeRegExp(modelSearch.value);
48
59
  });
49
60
 
61
+ const getDomLabel = id => {
62
+ if (!isBrowser()) {
63
+ return undefined;
64
+ }
65
+ const LINK = document.getElementById(getElementId({
66
+ menuId: menuId.value,
67
+ id,
68
+ suffix: "link",
69
+ }));
70
+ // Read source panels only; search results contain copies of the same links.
71
+ if (!LINK?.closest(".a_menu__panels__main:not(.a_menu__panel_search)")) {
72
+ return undefined;
73
+ }
74
+ return (LINK.querySelector(".a_menu__link__text") || LINK).textContent;
75
+ };
76
+
77
+ // shortcut: DOM translations refresh on query changes; observe mutations if live updates are needed.
50
78
  const itemsWithSearch = computed(() => {
51
79
  const ITEMS = [];
52
80
  if (isSearchActive.value) {
53
81
  const RE = new RegExp(modelSearchEscapeRegExp.value, "gi");
54
82
  forEach(dataKeyById.value, item => {
55
- const ITEM_LABEL = item[AKeyLabel];
56
- if (`${ ITEM_LABEL }`.search(RE) !== -1) {
83
+ const ITEM_LABEL = searchInDom.value ? getDomLabel(item[AKeyId]) : item[AKeyLabel];
84
+ if (searchInDom.value && ITEM_LABEL === undefined) {
85
+ return;
86
+ }
87
+ if (`${ ITEM_LABEL }`.search(RE) === -1) {
88
+ return;
89
+ }
90
+ if (!searchInDom.value) {
57
91
  ITEMS.push(item);
92
+ return;
58
93
  }
94
+ ITEMS.push({
95
+ ...item,
96
+ [AKeyLabel]: ITEM_LABEL,
97
+ [AKeyBreadcrumbs]: map(item[AKeyBreadcrumbs], breadcrumb => ({
98
+ ...breadcrumb,
99
+ label: getDomLabel(breadcrumb.parentId) ?? breadcrumb.label,
100
+ })),
101
+ });
59
102
  });
60
103
  }
61
104
  return ITEMS;
@@ -0,0 +1,108 @@
1
+ import {
2
+ computed,
3
+ reactive,
4
+ } from "vue";
5
+ import {
6
+ afterEach,
7
+ beforeEach,
8
+ describe,
9
+ expect,
10
+ it,
11
+ } from "vitest";
12
+
13
+ import LabelAPI from "../../AMenuPanelLink/compositionAPI/LabelAPI";
14
+ import SearchAPI from "../SearchAPI";
15
+
16
+ import AKeyBreadcrumbs from "../../const/AKeyBreadcrumbs";
17
+ import {
18
+ AKeyId,
19
+ AKeyLabel,
20
+ } from "../../../const/AKeys";
21
+
22
+ describe("AMenu search", () => {
23
+ const ITEMS = {
24
+ forms: { [AKeyId]: "forms", [AKeyLabel]: "Forms" },
25
+ input: {
26
+ [AKeyId]: "input",
27
+ [AKeyLabel]: "Input",
28
+ [AKeyBreadcrumbs]: [{ parentId: "forms", label: "Forms" }],
29
+ to: { name: "input" },
30
+ disabled: true,
31
+ },
32
+ missing: { [AKeyId]: "missing", [AKeyLabel]: "Eingabe missing" },
33
+ };
34
+
35
+ beforeEach(() => {
36
+ document.body.innerHTML = `
37
+ <nav id="test_menu">
38
+ <div class="a_menu__panels__main">
39
+ <a id="test_menu_forms_link"><span class="a_menu__link__text">Formulare</span></a>
40
+ <div style="display: none">
41
+ <a id="test_menu_input_link">
42
+ <span class="a_menu__link__text"><span>Eingabe</span> [DE]</span>
43
+ <span class="a_menu__link__counter">99</span>
44
+ </a>
45
+ </div>
46
+ </div>
47
+ <div class="a_menu__panels__main a_menu__panel_search">
48
+ <a id="test_menu_input_link"><span class="a_menu__link__text">Stale result</span></a>
49
+ <a id="test_menu_missing_link"><span class="a_menu__link__text">Eingabe missing</span></a>
50
+ </div>
51
+ </nav>`;
52
+ });
53
+
54
+ afterEach(() => {
55
+ document.body.innerHTML = "";
56
+ });
57
+
58
+ it("searches data by default even when DOM text differs", () => {
59
+ const search = SearchAPI(reactive({ menuId: "test_menu" }), {
60
+ dataKeyById: computed(() => ITEMS),
61
+ });
62
+ search.updateModelSearch("INPUT");
63
+ expect(search.itemsWithSearch.value).toEqual([ITEMS.input]);
64
+ expect(search.itemsWithSearch.value[0]).toBe(ITEMS.input);
65
+ search.updateModelSearch("Formulare");
66
+ expect(search.itemsWithSearch.value).toEqual([]);
67
+ });
68
+
69
+ it("searches translated text in source panels and preserves link behavior and breadcrumbs", () => {
70
+ const search = SearchAPI(reactive({ menuId: "test_menu", searchInDom: true }), {
71
+ dataKeyById: computed(() => ITEMS),
72
+ });
73
+ search.updateModelSearch("eINGABE");
74
+ expect(search.itemsWithSearch.value).toEqual([{
75
+ ...ITEMS.input,
76
+ [AKeyLabel]: "Eingabe [DE]",
77
+ [AKeyBreadcrumbs]: [{ parentId: "forms", label: "Formulare" }],
78
+ }]);
79
+ const {
80
+ label,
81
+ } = LabelAPI(reactive({
82
+ item: search.itemsWithSearch.value[0],
83
+ isLinkInSearchPanel: true,
84
+ modelSearch: "eINGABE",
85
+ }));
86
+ expect(label.value).toBe("<mark class=\"a_search_highlight\">Eingabe</mark> [DE]");
87
+ expect(ITEMS.input[AKeyLabel]).toBe("Input");
88
+ expect(ITEMS.input[AKeyBreadcrumbs][0].label).toBe("Forms");
89
+ search.updateModelSearch("Input");
90
+ expect(search.itemsWithSearch.value).toEqual([]);
91
+ search.updateModelSearch("99");
92
+ expect(search.itemsWithSearch.value).toEqual([]);
93
+ });
94
+
95
+ it("treats regular expression characters literally and rereads DOM for the next query", () => {
96
+ const search = SearchAPI(reactive({ menuId: "test_menu", searchInDom: true }), {
97
+ dataKeyById: computed(() => ITEMS),
98
+ });
99
+ search.updateModelSearch("[DE]");
100
+ expect(search.itemsWithSearch.value).toHaveLength(1);
101
+ document.querySelector("#test_menu_input_link .a_menu__link__text").textContent = "Saisie (FR)";
102
+ search.updateModelSearch("(FR)");
103
+ expect(search.itemsWithSearch.value[0][AKeyLabel]).toBe("Saisie (FR)");
104
+ search.resetSearch();
105
+ expect(search.isSearchActive.value).toBe(false);
106
+ expect(search.itemsWithSearch.value).toEqual([]);
107
+ });
108
+ });
@@ -274,6 +274,11 @@ export default {
274
274
  type: Boolean,
275
275
  required: false,
276
276
  },
277
+ readonlyValueParentClass: {
278
+ type: [String, Object, Array],
279
+ required: false,
280
+ default: undefined,
281
+ },
277
282
  readonlyDefault: {
278
283
  type: String,
279
284
  required: false,
@@ -623,6 +628,7 @@ export default {
623
628
  if (this.readonly) {
624
629
  return h(AFormReadonly, {
625
630
  ...this.$attrs,
631
+ valueParentClass: this.readonlyValueParentClass,
626
632
  id: this.htmlIdLocal,
627
633
  alwaysTranslate: this.alwaysTranslate,
628
634
  excludeRenderAttributes: this.excludeRenderAttributes,
@@ -97,6 +97,11 @@ export default {
97
97
  type: Boolean,
98
98
  required: false,
99
99
  },
100
+ readonlyValueParentClass: {
101
+ type: [String, Object, Array],
102
+ required: false,
103
+ default: undefined,
104
+ },
100
105
  searching: {
101
106
  type: Boolean,
102
107
  required: false,
@@ -190,6 +195,7 @@ export default {
190
195
  render() {
191
196
  if (this.readonly) {
192
197
  return h(AElement, {
198
+ class: this.readonlyValueParentClass,
193
199
  alwaysTranslate: this.alwaysTranslate,
194
200
  classDefault: "",
195
201
  extra: {
@@ -206,6 +206,11 @@ export default {
206
206
  type: Boolean,
207
207
  required: false,
208
208
  },
209
+ readonlyValueParentClass: {
210
+ type: [String, Object, Array],
211
+ required: false,
212
+ default: undefined,
213
+ },
209
214
  readonlyDefault: {
210
215
  type: String,
211
216
  required: false,
@@ -555,6 +560,7 @@ export default {
555
560
  if (this.readonly) {
556
561
  return h(AFormReadonly, {
557
562
  ...this.$attrs,
563
+ valueParentClass: this.readonlyValueParentClass,
558
564
  id: this.htmlIdLocal,
559
565
  alwaysTranslate: this.alwaysTranslate,
560
566
  class: this.class,
@@ -246,6 +246,11 @@ export default {
246
246
  type: Boolean,
247
247
  required: false,
248
248
  },
249
+ readonlyValueParentClass: {
250
+ type: [String, Object, Array],
251
+ required: false,
252
+ default: undefined,
253
+ },
249
254
  readonlyDefault: {
250
255
  type: String,
251
256
  required: false,
@@ -385,7 +390,7 @@ export default {
385
390
  required: this.required,
386
391
  style: this.componentStyleHide,
387
392
  type: "dateRange",
388
- valueParentClass: "a_form_element_readonly_value_range",
393
+ valueParentClass: ["a_form_element_readonly_value_range", this.readonlyValueParentClass],
389
394
  }, () => [
390
395
  h(ADatepicker, {
391
396
  id: this.idFrom,
@@ -205,6 +205,11 @@ export default {
205
205
  type: Boolean,
206
206
  required: false,
207
207
  },
208
+ readonlyValueParentClass: {
209
+ type: [String, Object, Array],
210
+ required: false,
211
+ default: undefined,
212
+ },
208
213
  readonlyDefault: {
209
214
  type: String,
210
215
  required: false,
@@ -409,6 +414,7 @@ export default {
409
414
  idPrefix: this.idPrefix,
410
415
  onUpdateData: ({ dataKeyByKeyId }) => this.onUpdateDataLocal({ item, dataKeyByKeyId }),
411
416
  class: classColumn,
417
+ readonlyValueParentClass: this.readonlyValueParentClass,
412
418
  ...item,
413
419
  change: ({ currentModel, id, item: _item, model, props, fullModel }) => this.onUpdateModelLocal({
414
420
  currentModel, id, item: _item, model, props, component: item, fullModel,
@@ -451,7 +457,7 @@ export default {
451
457
  required: this.required,
452
458
  style: this.componentStyleHide,
453
459
  type: "fieldset",
454
- valueParentClass: this.classColumnsReadonly,
460
+ valueParentClass: [this.classColumnsReadonly, this.readonlyValueParentClass],
455
461
  }, () => CONTENT);
456
462
  }
457
463
 
@@ -86,6 +86,11 @@ export default {
86
86
  type: Boolean,
87
87
  required: false,
88
88
  },
89
+ readonlyValueParentClass: {
90
+ type: [String, Object, Array],
91
+ required: false,
92
+ default: undefined,
93
+ },
89
94
  readonlyDefault: {
90
95
  type: String,
91
96
  required: false,
@@ -246,6 +251,7 @@ export default {
246
251
  useFlatModel: IS_CONTAINER ? this.useFlatModel : undefined,
247
252
  idPrefix: this.idPrefix,
248
253
  excludeRenderAttributes: this.excludeRenderAttributes,
254
+ readonlyValueParentClass: this.readonlyValueParentClass,
249
255
  ...item,
250
256
  change: ({ currentModel, id, item: _item, model, props, fullModel }) => this.onUpdateModelLocal({
251
257
  currentModel, id, item: _item, model, props, component: item, fullModel,
@@ -124,6 +124,11 @@ export default {
124
124
  type: Boolean,
125
125
  required: false,
126
126
  },
127
+ readonlyValueParentClass: {
128
+ type: [String, Object, Array],
129
+ required: false,
130
+ default: undefined,
131
+ },
127
132
  readonlyDefault: {
128
133
  type: String,
129
134
  required: false,
@@ -100,7 +100,7 @@ export default {
100
100
  default: undefined,
101
101
  },
102
102
  valueParentClass: {
103
- type: [String, Object],
103
+ type: [String, Object, Array],
104
104
  required: false,
105
105
  default: undefined,
106
106
  },
@@ -170,6 +170,11 @@ export default {
170
170
  type: Boolean,
171
171
  required: false,
172
172
  },
173
+ readonlyValueParentClass: {
174
+ type: [String, Object, Array],
175
+ required: false,
176
+ default: undefined,
177
+ },
173
178
  readonlyDefault: {
174
179
  type: String,
175
180
  required: false,
@@ -328,7 +333,7 @@ export default {
328
333
  "aria-describedby": this.ariaDescribedbyLocal,
329
334
  }, [
330
335
  h("div", {
331
- class: this.classColumns,
336
+ class: [this.classColumns, this.readonly && this.readonlyValueParentClass],
332
337
  }, [
333
338
  this.firstChild.label && h(ALabel, {
334
339
  id: this.htmlIdFirstChild,
@@ -394,10 +399,12 @@ export default {
394
399
  parentId,
395
400
  idPrefix: this.idPrefix,
396
401
  onUpdateData: ({ dataKeyByKeyId }) => this.onUpdateDataLocal({ item, dataKeyByKeyId }),
402
+ readonlyValueParentClass: this.readonlyValueParentClass,
397
403
  ...item,
398
404
  change: ({ currentModel, id, item: _item, model, props }) => this.onUpdateModelLocal({
399
405
  currentModel, id, item: _item, model, props, component: item,
400
406
  }),
407
+ readonly: this.readonly || item.readonly,
401
408
  disabled: this.disabled || item.disabled,
402
409
  ...this.specificAttributes[item.id],
403
410
  label: itemIndex === 0 ? undefined : item.label,
@@ -199,6 +199,11 @@ export default {
199
199
  type: Boolean,
200
200
  required: false,
201
201
  },
202
+ readonlyValueParentClass: {
203
+ type: [String, Object, Array],
204
+ required: false,
205
+ default: undefined,
206
+ },
202
207
  readonlyDefault: {
203
208
  type: String,
204
209
  required: false,
@@ -374,6 +379,7 @@ export default {
374
379
  if (this.readonly) {
375
380
  return h(AFormReadonly, {
376
381
  ...this.$attrs,
382
+ valueParentClass: this.readonlyValueParentClass,
377
383
  id: this.htmlIdLocal,
378
384
  alwaysTranslate: this.alwaysTranslate,
379
385
  excludeRenderAttributes: this.excludeRenderAttributes,
@@ -264,6 +264,11 @@ export default {
264
264
  type: Boolean,
265
265
  required: false,
266
266
  },
267
+ readonlyValueParentClass: {
268
+ type: [String, Object, Array],
269
+ required: false,
270
+ default: undefined,
271
+ },
267
272
  readonlyDefault: {
268
273
  type: String,
269
274
  required: false,
@@ -451,6 +456,7 @@ export default {
451
456
  if (this.readonly) {
452
457
  return h(AFormReadonly, {
453
458
  ...this.$attrs,
459
+ valueParentClass: this.readonlyValueParentClass,
454
460
  id: this.htmlIdLocal,
455
461
  alwaysTranslate: this.alwaysTranslate,
456
462
  excludeRenderAttributes: this.excludeRenderAttributes,
@@ -6,6 +6,7 @@ import {
6
6
  } from "vue";
7
7
  import {
8
8
  AFormLabelDescription,
9
+ AFormReadonly,
9
10
  } from "../../index";
10
11
 
11
12
  import AErrorsText from "../AErrorsText/AErrorsText";
@@ -57,6 +58,20 @@ export default {
57
58
  type: [String, Number, Object, Array],
58
59
  required: false,
59
60
  },
61
+ readonly: {
62
+ type: Boolean,
63
+ required: false,
64
+ },
65
+ readonlyDefault: {
66
+ type: String,
67
+ required: false,
68
+ default: "",
69
+ },
70
+ readonlyValueParentClass: {
71
+ type: [String, Object, Array],
72
+ required: false,
73
+ default: undefined,
74
+ },
60
75
  text: {
61
76
  type: String,
62
77
  required: false,
@@ -164,6 +179,26 @@ export default {
164
179
  return null;
165
180
  }
166
181
 
182
+ if (this.readonly) {
183
+ return h(AFormReadonly, {
184
+ ...this.$attrs,
185
+ id: this.htmlIdLocal,
186
+ alwaysTranslate: this.alwaysTranslate,
187
+ excludeRenderAttributes: this.excludeRenderAttributes,
188
+ extra: this.extra,
189
+ helpText: this.helpText,
190
+ label: this.label,
191
+ labelClass: this.labelClass,
192
+ labelScreenReader: this.labelScreenReader,
193
+ readonlyDefault: this.readonlyDefault,
194
+ style: this.componentStyleHide,
195
+ type: this.type,
196
+ valueParentClass: this.readonlyValueParentClass,
197
+ }, this.isModel ?
198
+ () => h("ul", {}, this.modelValueListLocal.map(model => h("li", {}, model.name))) :
199
+ undefined);
200
+ }
201
+
167
202
  return h("div", {
168
203
  ...this.$attrs,
169
204
  style: this.componentStyleHide,
@@ -172,11 +207,11 @@ export default {
172
207
  h("div", {
173
208
  class: "a_form_element__parent",
174
209
  }, [
175
- this.label && h(ALabel, {
176
- id: this.htmlIdLocal,
177
- alwaysTranslate: this.alwaysTranslate,
178
- extra: this.extra,
179
- label: this.label,
210
+ this.label && h(ALabel, {
211
+ id: this.htmlIdLocal,
212
+ alwaysTranslate: this.alwaysTranslate,
213
+ extra: this.extra,
214
+ label: this.label,
180
215
  labelClass: this.labelClass,
181
216
  labelScreenReader: this.labelScreenReader,
182
217
  required: this.required,
@@ -139,6 +139,11 @@ export default {
139
139
  type: Boolean,
140
140
  required: false,
141
141
  },
142
+ readonlyValueParentClass: {
143
+ type: [String, Object, Array],
144
+ required: false,
145
+ default: undefined,
146
+ },
142
147
  readonlyDefault: {
143
148
  type: String,
144
149
  required: false,
@@ -331,6 +336,7 @@ export default {
331
336
  if (this.readonly) {
332
337
  return h(AFormReadonly, {
333
338
  ...this.$attrs,
339
+ valueParentClass: this.readonlyValueParentClass,
334
340
  id: this.htmlIdLocal,
335
341
  alwaysTranslate: this.alwaysTranslate,
336
342
  excludeRenderAttributes: this.excludeRenderAttributes,
@@ -214,6 +214,11 @@ export default {
214
214
  type: Boolean,
215
215
  required: false,
216
216
  },
217
+ readonlyValueParentClass: {
218
+ type: [String, Object, Array],
219
+ required: false,
220
+ default: undefined,
221
+ },
217
222
  readonlyDefault: {
218
223
  type: String,
219
224
  required: false,
@@ -368,7 +373,7 @@ export default {
368
373
  required: this.required,
369
374
  style: this.componentStyleHide,
370
375
  type: "numberRange",
371
- valueParentClass: "a_form_element_readonly_value_range",
376
+ valueParentClass: ["a_form_element_readonly_value_range", this.readonlyValueParentClass],
372
377
  }, () => [
373
378
  h(AInputNumber, {
374
379
  id: this.idMin,
@@ -161,6 +161,11 @@ export default {
161
161
  type: Boolean,
162
162
  required: false,
163
163
  },
164
+ readonlyValueParentClass: {
165
+ type: [String, Object, Array],
166
+ required: false,
167
+ default: undefined,
168
+ },
164
169
  readonlyDefault: {
165
170
  type: String,
166
171
  required: false,
@@ -267,6 +272,7 @@ export default {
267
272
  if (this.readonly) {
268
273
  return h(AFormReadonly, {
269
274
  ...this.$attrs,
275
+ valueParentClass: this.readonlyValueParentClass,
270
276
  id: this.htmlIdLocal,
271
277
  alwaysTranslate: this.alwaysTranslate,
272
278
  excludeRenderAttributes: this.excludeRenderAttributes,