Skip to content

Commit d6edf4b

Browse files
authored
Improve label handling in Angular MasterListComponent
The Angular MasterListComponent did only show labels for object lists. Furthermore the options property in the uischema was mandatory. Also the property to use as label for objects had to be provided. The fix now handles primitives, a missing options property and in the case of a missing `labelRef` the first primitive property is used. If no primitive property is available the fallback text 'No label set' will be shown. Fix #1779
1 parent eb77c4a commit d6edf4b

File tree

4 files changed

+192
-7
lines changed

4 files changed

+192
-7
lines changed

packages/angular-material/src/other/master-detail/master.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
ControlElement,
3535
createDefaultValue,
3636
findUISchema,
37+
getFirstPrimitiveProp,
3738
JsonFormsState,
3839
mapDispatchToArrayControlProps,
3940
mapStateToArrayControlProps,
@@ -169,22 +170,22 @@ export class MasterListComponent extends JsonFormsArrayControl {
169170
const { data, path, schema, uischema } = props;
170171
const controlElement = uischema as ControlElement;
171172
this.propsPath = props.path;
172-
const detailUISchema =
173-
controlElement.options.detail ||
174-
findUISchema(
173+
const detailUISchema = findUISchema(
175174
props.uischemas,
176175
schema,
177176
`${controlElement.scope}/items`,
178177
props.path,
179-
'VerticalLayout'
178+
'VerticalLayout',
179+
controlElement
180180
);
181181

182182
const masterItems = (data || []).map((d: any, index: number) => {
183-
const labelRefInstancePath = removeSchemaKeywords(
183+
const labelRefInstancePath = controlElement.options?.labelRef && removeSchemaKeywords(
184184
controlElement.options.labelRef
185185
);
186+
const isPrimitive = d !== undefined && typeof d !== 'object';
186187
const masterItem = {
187-
label: get(d, labelRefInstancePath),
188+
label: isPrimitive ? d.toString() : get(d, labelRefInstancePath ?? getFirstPrimitiveProp(schema)),
188189
data: d,
189190
path: `${path}.${index}`,
190191
schema,

packages/examples/src/1779.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
The MIT License
3+
4+
Copyright (c) 2017-2021 EclipseSource Munich
5+
https://github.com/eclipsesource/jsonforms
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in
15+
all copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
THE SOFTWARE.
24+
*/
25+
import { registerExamples } from './register';
26+
27+
const data = {
28+
'an-array-of-strings': ['foo', 'bar', 'foobar']
29+
};
30+
const schema = {
31+
type: 'object',
32+
properties: {
33+
'an-array-of-strings': {
34+
type: 'array',
35+
items: {
36+
type: 'string'
37+
}
38+
}
39+
}
40+
};
41+
const uischema = {
42+
"type": "ListWithDetail",
43+
"scope": "#/properties/an-array-of-strings"
44+
};
45+
46+
registerExamples([
47+
{
48+
name: '1779-string',
49+
label: 'List With Detail primitive (string)',
50+
data,
51+
schema,
52+
uischema
53+
}
54+
]);
55+
56+
const data_number = {
57+
'an-array-of-numbers': [1, 2, 3]
58+
};
59+
const schema_number = {
60+
type: 'object',
61+
properties: {
62+
'an-array-of-numbers': {
63+
type: 'array',
64+
items: {
65+
type: 'number'
66+
}
67+
}
68+
}
69+
};
70+
const uischema_number = {
71+
"type": "ListWithDetail",
72+
"scope": "#/properties/an-array-of-numbers"
73+
};
74+
75+
registerExamples([
76+
{
77+
name: '1779-number',
78+
label: 'List With Detail primitive (number)',
79+
data: data_number,
80+
schema: schema_number,
81+
uischema: uischema_number
82+
}
83+
]);

packages/examples/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import * as booleanToggle from './booleanToggle';
7474
import * as multiEnum from './multi-enum';
7575
import * as enumInArray from './enumInArray';
7676
import * as readonly from './readonly';
77+
import * as bug_1779 from './1779';
7778
export * from './register';
7879
export * from './example';
7980

@@ -132,5 +133,6 @@ export {
132133
booleanToggle,
133134
multiEnum,
134135
enumInArray,
135-
readonly
136+
readonly,
137+
bug_1779
136138
};

packages/examples/src/list-with-detail.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,95 @@ const uischema = {
195195
}
196196
};
197197

198+
const uischemaNoLabelRef = {
199+
type: 'ListWithDetail',
200+
scope: '#/properties/orders',
201+
options: {
202+
detail: {
203+
type: 'VerticalLayout',
204+
elements: [
205+
{
206+
type: 'HorizontalLayout',
207+
elements: [
208+
{
209+
type: 'Control',
210+
scope: '#/properties/title'
211+
},
212+
{
213+
type: 'Control',
214+
scope: '#/properties/processId'
215+
}
216+
]
217+
},
218+
{
219+
type: 'Group',
220+
label: 'Customer',
221+
elements: [
222+
{
223+
type: 'Control',
224+
label: 'ID',
225+
scope: '#/properties/customer/properties/id'
226+
},
227+
{
228+
type: 'Control',
229+
label: 'Name',
230+
scope: '#/properties/customer/properties/name'
231+
},
232+
{
233+
type: 'Control',
234+
label: 'Department',
235+
scope: '#/properties/customer/properties/department'
236+
}
237+
]
238+
},
239+
{
240+
type: 'VerticalLayout',
241+
elements: [
242+
{
243+
type: 'VerticalLayout',
244+
elements: [
245+
{
246+
type: 'HorizontalLayout',
247+
elements: [
248+
{
249+
type: 'Control',
250+
scope: '#/properties/ordered',
251+
options: {
252+
toggle: true
253+
}
254+
},
255+
{
256+
type: 'Control',
257+
scope: '#/properties/assignee'
258+
}
259+
]
260+
},
261+
{
262+
type: 'HorizontalLayout',
263+
elements: [
264+
{
265+
type: 'Control',
266+
scope: '#/properties/startDate'
267+
},
268+
{
269+
type: 'Control',
270+
scope: '#/properties/endDate'
271+
}
272+
]
273+
},
274+
{
275+
type: 'Control',
276+
scope: '#/properties/status'
277+
}
278+
]
279+
}
280+
]
281+
}
282+
]
283+
}
284+
}
285+
};
286+
198287
registerExamples([
199288
{
200289
name: 'list-with-detail',
@@ -204,3 +293,13 @@ registerExamples([
204293
uischema
205294
}
206295
]);
296+
297+
registerExamples([
298+
{
299+
name: 'list-with-detail-no-labelref',
300+
label: 'List With Detail (No Label Ref)',
301+
data,
302+
schema,
303+
uischema:uischemaNoLabelRef
304+
}
305+
]);

0 commit comments

Comments
 (0)