I am making a custom angular renderer for oneOf, and it works fine with a single oneOf object. However, if I make the schema contain an array of oneOf objects, the schema that gets passed into the renderer becomes incorrect.
For example, with the following schema, the definitions section just disappears, and then the schema is unable to parse the references in the oneOf. When I look into the renderer instance, I can see that it has a jsonFormsService object that contains the correct schema, but for some reason the instance is using its own version of the schema.
Schema:
{
"definitions": {
"address": {
"type": "object",
"title": "Address",
"properties": {
"street_address": {
"type": "string"
},
"city": {
"type": "string"
},
"state": {
"type": "string"
}
},
"required": ["street_address", "city", "state"]
},
"user": {
"type": "object",
"title": "User",
"properties": {
"name": {
"type": "string"
},
"mail": {
"type": "string"
}
},
"required": ["name", "mail"]
}
},
"type": "array",
"items": {
"type": "object",
"properties": {
"addressOrUser": {
"oneOf": [
{
"$ref": "#/definitions/address"
},
{
"$ref": "#/definitions/user"
}
]
}
}
}
}
Here is the renderer:
import { ChangeDetectorRef, Component } from "@angular/core";
import { JsonFormsAngularService, JsonFormsControl } from "@jsonforms/angular";
import { angularMaterialRenderers } from "@jsonforms/angular-material";
import { JsonSchema, resolveSchema } from "@jsonforms/core";
@Component({
selector: "oneOf-renderer",
template: `
<div>
<label>{{ label }}</label>
<select (change)="onOptionChange($event)">
<option *ngFor="let option of options" [value]="option.title">
{{ option.title }}
</option>
</select>
<jsonforms
*ngIf="shouldRenderJsonForms"
[data]="data"
[schema]="selectedOption"
[renderers]="this.renderers"
></jsonforms>
</div>
`,
})
export class oneOfRenderer extends JsonFormsControl {
renderers = [...angularMaterialRenderers];
options: any;
selectedOption: any;
shouldRenderJsonForms = false; // Used to mount/unmount the json form html because it doesn't refresh when a new schema is provided
constructor(jsonFormsService: JsonFormsAngularService, private cdr: ChangeDetectorRef) {
super(jsonFormsService);
}
ngOnInit() {
console.log(this);
// this.options = this.extractOptions(this.schema);
// if (this.options.length > 0) {
// this.selectedOption = this.options[0];
// }
// this.shouldRenderJsonForms = true;
}
onOptionChange(event: any) {
this.shouldRenderJsonForms = false;
this.selectedOption = this.options.find(
(option) => option.title === event.target.value
);
console.log(event.target);
this.cdr.detectChanges();
this.shouldRenderJsonForms = true;
}
extractOptions(schema: JsonSchema) {
console.log(schema);
for (const key in schema.properties) {
if (schema.properties.hasOwnProperty(key)) {
const property = schema.properties[key];
if (property.oneOf) {
const refs = property.oneOf.map((option: any) => option);
console.log(refs);
const options = [];
for (const key in refs) {
console.log(refs[key]["$ref"]);
options.push(resolveSchema(schema, refs[key]["$ref"], schema));
}
console.log(options);
return options;
}
}
}
}
}
