Closed
Description
Prerequisites
- I have read the documentation
What theme are you using?
other
Is your feature request related to a problem? Please describe.
Hello everyone, I'm opening this discussion because I had trouble figuring out a way to customize my form layouts. I wanted to demonstrate how I achieved this in code.
Describe the solution you'd like
this is my ui schema
const uiSchema: UiSchema<typeof schema> = {
'ui:layout': {
type: 'grid',
cols: 2,
},
personalData: {
'ui:layout': 'flex-col',
},
}
this is my json schema
const schema: RJSFSchema = {
type: 'object',
title: 'Columns',
properties: {
name: {
type: 'string',
minLength: 3,
description: 'Please enter your name',
},
vegetarian: {
type: 'boolean',
},
birthDate: {
type: 'string',
format: 'date',
},
nationality: {
type: 'string',
enum: ['DE', 'IT', 'JP', 'US', 'RU', 'Other'],
},
personalData: {
type: 'object',
properties: {
age: {
type: 'integer',
description: 'Please enter your age.',
},
height: {
type: 'number',
},
drivingSkill: {
type: 'number',
maximum: 10,
minimum: 1,
default: 7,
},
},
required: ['age', 'height'],
},
occupation: {
type: 'string',
},
postalCode: {
type: 'string',
maxLength: 5,
},
},
required: ['occupation', 'nationality'],
}
notice the "ui:layout"
property on the uiSchema object. I used that property to map my ObjectFieldTemplate
. So in the example, the first object will recieve the grid + 2 cols. and the personalData will recieve the flex-col
. This way I conditionally render inside my custom ObjectFieldTemplate
:)
kinda like this
export const ObjectFieldTemplate = (props: ObjectFieldTemplateProps) => {
const maybeOptions = props.uiSchema?.['ui:layout'] as unknown
if (maybeOptions === undefined || maybeOptions === null) return <DefaultFlexObjectFieldTemplate {...props} />
else if (typeof maybeOptions === 'string') {
const options = maybeOptions.split(' ')
if (options.length > 1) {
console.warn('ui:layout can only have one option, defaulting to flex-row')
return <DefaultFlexObjectFieldTemplate {...props} />
}
switch (maybeOptions) {
case 'grid':
return <DefaultGridObjectFieldTemplate {...props} />
case 'flex-col':
return <DefaultFlexColObjectFieldTemplate {...props} />
case 'flex-row':
default:
return <DefaultFlexObjectFieldTemplate {...props} />
}
} else if (typeof maybeOptions === 'object') {
const { type, cols } = maybeOptions as { type?: unknown; cols?: unknown }
if (type === 'grid') {
if (typeof cols !== 'number') return <DefaultGridObjectFieldTemplate {...props} />
else {
if (cols > 5 || cols < 1) {
console.warn('cols must be between 1 and 5, defaulting to 5')
}
const validCols = Math.min(Math.max(cols, 1), 5)
return <DefaultGridObjectFieldTemplate {...props} cols={validCols} />
}
}
}
return <DefaultFlexObjectFieldTemplate {...props} />
}
Describe alternatives you've considered
I had to do this because I did not find a way to achieve this natively. I know the ui:className
property is also there but I wanted to render my own custom components so that wasnt enough.