Bridges
To make use of any schema, uniforms have to create a bridge of it - a unified schema mapper.
Currently available bridges:
JSONSchemaBridge
inuniforms-bridge-json-schema
(schema documentation)SimpleSchema2Bridge
inuniforms-bridge-simple-schema-2
(schema documentation)ZodBridge
inuniforms-bridge-zod
(schema documentation)
Deprecated bridges:
SimpleSchemaBridge
inuniforms-bridge-simple-schema
(schema documentation)GraphQLBridge
inuniforms-bridge-graphql
(schema documentation)
If you see a lot of Warning: Unknown props...
logs, check if your schema or theme doesn't provide extra props. If so, consider registering it with filterDOMProps
.
JSONSchemaBridge
import Ajv from 'ajv';
import { JSONSchemaBridge } from 'uniforms-bridge-json-schema';
const ajv = new Ajv({ allErrors: true, useDefaults: true });
const schema = {
title: 'Person',
type: 'object',
properties: {
firstName: { type: 'string' },
lastName: { type: 'string' },
age: {
description: 'Age in years',
type: 'integer',
minimum: 0,
},
},
required: ['firstName', 'lastName'],
};
function createValidator(schema: object) {
const validator = ajv.compile(schema);
return (model: object) => {
validator(model);
return validator.errors?.length ? { details: validator.errors } : null;
};
}
const validator = createValidator(schema);
const bridge = new JSONSchemaBridge({ schema, validator });
Note on allOf
/anyOf
/oneOf
The current handling of allOf
/anyOf
/oneOf
is not complete and does not work with all possible cases. For an in-detail discussion, see #863. How it works, is that only a few properties are being used:
properties
, where all subfields are merged (last definition wins),required
, where all properties are accumulated, andtype
, where the first one is being used.
Below is an example of these implications:
{
"type": "object",
"properties": {
// This will render `NumField` WITHOUT `min` nor `max` properties.
// It will be properly validated, but without any UI guidelines.
"foo": {
"type": "number",
"allOf": [{ "minimum": 0 }, { "maximum": 10 }]
},
// This will render as `TextField`.
"bar": {
"oneOf": [{ "type": "string" }, { "type": "number" }]
}
}
}
Note on Bluebird
If you're using the bluebird
package, you may have seen the following warning (docs):
Warning: a promise was rejected with a non-error [object Object]
There could be multiple causes of this error. One of it is not returning a proper error object.
In order to fix it, your validator
function should return a Error
-like object instead of an object with a single details
property. The cleanest would be to create a custom ValidationError
class:
import { ErrorObject } from 'ajv';
class ValidationError extends Error {
name = 'ValidationError';
constructor(public details: ErrorObject[]) {
super('ValidationError');
}
}
// Usage.
return validator.errors?.length ? new ValidationError(validator.errors) : null;
Another cause of this error may be two different implementations of the Promise
object when using an asynchronous validate function.
Ensure that you are returning the same Promise
object implementation that Bluebird is expecting.
The simplest way to do that should be to avoid using the async
keyword and instead make the function return a Promise
instead.
See #1047 for more details.
SimpleSchema2Bridge
import SimpleSchema from 'simpl-schema';
import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2';
const schema = new SimpleSchema({
// ...
aboutMe: {
type: String,
uniforms: MyText, // Component...
uniforms: {
// ...or object...
component: MyText, // ...with component...
propA: 1, // ...and/or extra props.
},
},
});
const bridge = new SimpleSchema2Bridge({ schema });
ZodBridge
import ZodBridge from 'uniforms-bridge-zod';
import z from 'zod';
const schema = z.object({ aboutMe: z.string() });
const bridge = new ZodBridge({ schema });
## `ZodBridge`
```tsx
import ZodBridge from 'uniforms-bridge-zod';
import z from 'zod';
const schema = z.object({ aboutMe: z.string() });
const bridge = new ZodBridge({ schema });