Skip to content

Commit

Permalink
feat(json-schema): add support for adding custom labels to enum (#1802)
Browse files Browse the repository at this point in the history
  • Loading branch information
aitboudad committed Sep 27, 2019
1 parent ac8df86 commit a96c8fe
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class AppComponent {
'allOf',
'null_field',
'nullable',
'select_alternatives',
];

constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { AppComponent } from './app.component';
{ file: 'assets/json-schema/allOf.json', content: require('!!highlight-loader?raw=true&lang=typescript!@assets/json-schema/allOf_json'), filecontent: require('!!raw-loader!@assets/json-schema/allOf_json') },
{ file: 'assets/json-schema/null_field.json', content: require('!!highlight-loader?raw=true&lang=typescript!@assets/json-schema/null_field_json'), filecontent: require('!!raw-loader!@assets/json-schema/null_field_json') },
{ file: 'assets/json-schema/nullable.json', content: require('!!highlight-loader?raw=true&lang=typescript!@assets/json-schema/nullable_json'), filecontent: require('!!raw-loader!@assets/json-schema/nullable_json') },
{ file: 'assets/json-schema/select_alternatives.json', content: require('!!highlight-loader?raw=true&lang=typescript!@assets/json-schema/select_alternatives_json'), filecontent: require('!!raw-loader!@assets/json-schema/select_alternatives_json') },
],
}],
},
Expand Down
99 changes: 99 additions & 0 deletions demo/src/assets/json-schema/select_alternatives_json
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
"schema": {
"title": "Select alternatives",
"type": "object",
"properties": {
"select1": {
"type": "string",
"title": "Select 1: Enum array",
"enum": [
"Option 1",
"Option 2",
"Option 3"
]
},
"select2": {
"type": "string",
"title": "Select 2: AnyOf/OneOf array with enum",
"anyOf": [
{
"title": "Option 1",
"enum": [
"option1"
]
},
{
"title": "Option 2",
"enum": [
"option2"
]
},
{
"title": "Option 3",
"enum": [
"option3"
]
}
]
},
"select3": {
"type": "string",
"title": "Select 3: AnyOf/OneOf array with const",
"oneOf": [
{
"title": "Option 1",
"const": "option1"
},
{
"title": "Option 2",
"const": "option2"
},
{
"title": "Option 3",
"const": "option3"
}
]
},
"select4": {
"type": "string",
"title": "Select 4: Radio button",
"enum": [
"Option 1",
"Option 2",
"Option 3"
],
"widget": {
"formlyConfig": {
"type": "radio"
}
}
},
"select5": {
"type": "string",
"title": "Select 5: with widget attr",
"widget": {
"formlyConfig": {
"type": "enum",
"templateOptions": {
"options": [
{
"value": "1",
"label": "option 1"
},
{
"value": "2",
"label": "option 2"
},
{
"value": "3",
"label": "option 3"
}
]
}
}
}
}
}
},
"model": {}
}
43 changes: 36 additions & 7 deletions src/core/json-schema/src/formly-json-schema.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -487,15 +487,44 @@ describe('Service: FormlyJsonschema', () => {

});

// TODO: add support for adding custom labels to enum values using oneOf/const
// https://github.com/json-schema-org/json-schema-spec/issues/57#issuecomment-247861695
// it('should support enum as oneOf structure', () => {
// const schema: JSONSchema7 = {
// type: 'number',
// };
describe('enum as oneOf/anyOf structure', () => {
it('should support enum as oneOf/const structure', () => {
const schema: JSONSchema7 = {
type: 'number',
oneOf: [{ title: '1', const: 1 }, { title: '2', const: 2 }],
};

// const config = formlyJsonschema.toFieldConfig(schema);
// });
const { type, templateOptions: { options } } = formlyJsonschema.toFieldConfig(schema);

expect(type).toEqual('enum');
expect(options).toEqual([{ label: '1', value: 1 }, { label: '2', value: 2 }]);
});

it('should support enum as oneOf/enum structure', () => {
const schema: JSONSchema7 = {
type: 'number',
oneOf: [{ title: '1', enum: [1] }, { title: '2', enum: [2] }],
};

const { type, templateOptions: { options } } = formlyJsonschema.toFieldConfig(schema);

expect(type).toEqual('enum');
expect(options).toEqual([{ label: '1', value: 1 }, { label: '2', value: 2 }]);
});

it('should support enum as anyOf structure', () => {
const schema: JSONSchema7 = {
type: 'number',
anyOf: [{ title: '1', enum: [1] }, { title: '2', enum: [2] }],
};

const { type, templateOptions: { options } } = formlyJsonschema.toFieldConfig(schema);

expect(type).toEqual('enum');
expect(options).toEqual([{ label: '1', value: 1 }, { label: '2', value: 2 }]);
});
});

// TODO: discuss const support possibly as hidden, already set field
// it('should support cosnt', () => {
Expand Down
34 changes: 32 additions & 2 deletions src/core/json-schema/src/formly-json-schema.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ export class FormlyJsonschema {
}
}

if (schema.enum) {
if (this.isEnum(schema)) {
field.type = 'enum';
field.templateOptions.options = schema.enum.map(value => ({ value, label: value }));
field.templateOptions.options = this.toEnumOptions(schema);
}

// map in possible formlyConfig options from the widget property
Expand Down Expand Up @@ -285,4 +285,34 @@ export class FormlyJsonschema {
field.validators = field.validators || {};
field.validators[name] = validator;
}

private isEnum(schema: JSONSchema7) {
const isConst = (s: JSONSchema7) => s.hasOwnProperty('const') || (s.enum && s.enum.length === 1);

return schema.enum
|| (schema.anyOf && schema.anyOf.every(isConst))
|| (schema.oneOf && schema.oneOf.every(isConst));
}

private toEnumOptions(schema: JSONSchema7) {
if (schema.enum) {
return schema.enum.map(value => ({ value, label: value }));
}

const toEnum = (s: JSONSchema7) => {
const value = s.hasOwnProperty('const') ? s.const : s.enum[0];

return { value: value, label: s.title || value };
};

if (schema.anyOf) {
return schema.anyOf.map(toEnum);
}

if (schema.oneOf) {
return schema.oneOf.map(toEnum);
}

return [];
}
}

0 comments on commit a96c8fe

Please sign in to comment.