im using the package jsonforms/vue-vanilla and i am currently trying to solve a rendering issue with my fetched schema from an api.
what im trying to do is fetch a deeply nested oneOf property called resourceKindSpec and trying to merge it with the rest of the properties:
const fetchSchema = async () => {
try {
const schemaKey = 'CreateResource';
// Fetch and resolve schema
schema.value = await SchemaService.getSchemaByKey(schemaKey);
// Log the allOf arrays to see the structure
console.log('allOf[1]', schema.value.allOf[1]); // Additional properties
console.log('allOf[0]', schema.value.allOf[0]); // Base properties and oneOf schemas
// Extract properties from both allOf[0] and allOf[1]
const baseProperties = schema.value.allOf[0].properties || {};
const additionalProperties = schema.value.allOf[1].properties || {};
// Get the oneOf schemas from allOf[0]
const oneOfSchemas = schema.value.allOf[0].oneOf || [];
console.log('oneOfSchemas', oneOfSchemas);
// Find the matching schema based on x-quandago-resource-kind
const matchingSpec = oneOfSchemas.find(
(spec) => spec.properties?.spec['x-quandago-resource-kind'] === activeResourceKind.value
);
if (!matchingSpec) {
console.warn(`No matching spec found for ${activeResourceKind.value}`);
return;
}
// Extract the properties of the matched spec
const resourceKindSpec = matchingSpec.properties.spec.properties || {};
console.log('spec to be merged:', resourceKindSpec);
// Merge the base, additional, and resourceKindSpec properties
const mergedSchema = {
...schema.value.allOf[1], // Additional properties from allOf[1]
properties: {
...baseProperties, // Base properties from allOf[0]
...additionalProperties, // Additional properties from allOf[1]
...resourceKindSpec, // Matched spec properties
},
};
console.log('Merged schema:', mergedSchema);
// Generate the UI schema for the merged schema
uischema.value = generateUISchema(mergedSchema);
// Handle the api_version dynamically
const handleApiVersionChange = (selectedVersion) => {
const mapping = schema.value.allOf[0].discriminator.mapping;
const refSchema = mapping[selectedVersion];
const specSchemaKey = refSchema.split('/').pop();
fetchSpecSchema(specSchemaKey);
};
// Listen to changes in api_version
onMounted(() => {
watch(() => data.value.api_version, (newValue) => {
if (newValue) {
handleApiVersionChange(newValue);
}
});
});
// Generate UI schema for the matching oneOf schema
const oneOfUISchema = generateUISchema(matchingSpec);
uischema.value.elements.push(oneOfUISchema);
console.log('Final UI schema:', uischema.value);
} catch (error) {
console.error('Error fetching schema:', error);
} finally {
isLoading.value = false;
}
};
the schema generator is as follows:
const generateUISchema = (schema) => {
const uiElements = Object.keys(schema.properties).map((propertyKey) => {
return {
type: 'Control',
scope: `#/properties/${propertyKey}`,
};
});
// Add `api_version` if it's a required field and not in the properties
if (schema.required && schema.required.includes('api_version')) {
uiElements.unshift({
type: 'Control',
scope: '#/properties/api_version',
options: {
enum: [
'interactions/v1',
'sbc/v1',
'trunk/v1',
'transformationRules/v1',
'inboundRoutingRule/v1',
'outboundRoutingRule/v1',
],
},
});
}
// Debugging UI Elements
console.log('Generated UI Elements:', uiElements);
return {
type: 'VerticalLayout',
elements: uiElements,
};
};
the ui schema after merging is as follows:
[
{
"type": "Control",
"scope": "#/properties/display_name",
"options": {
"type": "text",
"validation": {
"minLength": 3
}
},
"label": "display_name"
},
{
"type": "Control",
"scope": "#/properties/description",
"options": {
"type": "text",
"validation": {
"maxLength": 512
}
},
"label": "description"
},
{
"type": "Control",
"scope": "#/properties/api_version",
"options": {
"type": "text"
},
"label": "api_version"
},
{
"type": "Control",
"scope": "#/properties/tags",
"options": {},
"label": "tags"
},
{
"type": "Control",
"scope": "#/properties/account_id",
"options": {
"type": "text"
},
"label": "account_id"
},
{
"type": "Control",
"scope": "#/properties/kind",
"options": {
"type": "text"
},
"label": "kind"
},
{
"type": "Control",
"scope": "#/properties/name",
"options": {
"type": "text",
"validation": {
"maxLength": 64,
"minLength": 3,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
}
},
"label": "name"
},
{
"type": "Control",
"scope": "#/properties/environment",
"options": {
"type": "text",
"validation": {
"maxLength": 64,
"minLength": 3,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
}
},
"label": "environment"
},
{
"type": "Control",
"scope": "#/properties/capacity",
"options": {
"type": "number"
},
"label": "capacity"
},
{
"type": "Control",
"scope": "#/properties/classic",
"options": {
"type": "checkbox"
},
"label": "classic"
},
{
"type": "Control",
"scope": "#/properties/domain",
"options": {
"type": "text",
"validation": {
"maxLength": 255,
"minLength": 3,
"pattern": "(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\\.)+[a-zA-Z]{2,63}$)"
}
},
"label": "domain"
},
{
"type": "Control",
"scope": "#/properties/tenant_guid",
"options": {
"type": "text",
"validation": {
"maxLength": 32,
"minLength": 32,
"pattern": "^[0-9a-f]+$"
}
},
"label": "tenant_guid"
},
{
"type": "Control",
"scope": "#/properties/tenant_shortname",
"options": {
"type": "text",
"validation": {
"maxLength": 16,
"minLength": 1,
"pattern": "^[a-z]+$"
}
},
"label": "tenant_shortname"
}
]
somehow the labels ‘capacity
’ until 'tenant_shortname'
are not being rendered:
i only see this text in their place:
No applicable renderer found.
No applicable renderer found.
No applicable renderer found.
No applicable renderer found.
No applicable renderer found.
is there something wrong with how i generated the schema?