Skip to main content

Helpers

connectField

Provides form management related props. The connectField helper is a component wrapper (higher order component, HOC), that provides various props related to the form management. It also adds the Field suffix to the name of the wrapped component.

The table below lists all of the guaranteed props that will be passed to the wrapped component:

NameTypeDescription
changedbooleanHas field changed?
disabledbooleanIs field disabled?
errorobjectField scoped part of validation error.
errorMessagestringField scoped validation error message.
fieldobjectField definition from schema.
fieldsarrayOf(string)Subfields names.
fieldTypefuncField type.
idstringField id - given or random.
labelstringField label.
namestringField name.
onChangefunc(value, [name])Change field value.
placeholderstringField placeholder.
readOnlybooleanIs field read-only?
showInlineErrorbooleanShow inline error?
valueanyField value.

The connectField function accepts two arguments: the first one is a component and the second one is an options object.

function Example(props) {
/* ... */
}

const ExampleField = connectField(Example, options);

The table below lists all available options:

NameTypeDescription
initialValuebooleanInitial value check. If true, then after the first render the default value is set as value if no value is provided (undefined).
kind'leaf' or 'node'See Field kinds.

Field kinds

Every field is either a leaf or node field. In the future, we could introduce new kinds to enable even more optimizations.

  • Leaf fields cannot have subfields. This allows us to perform some optimizations, like skipping the extra Provider from connectField, effectively reducing the overhead down to a single useField call.
    • It includes all input fields, like NumField, SelectField or TextField.
  • Node fields can have subfields. Fields of the leaf kind cannot have subfields.
    • It includes all combined and layout fields, like ListField or NestField.

If you are not sure which one to use, do not use the kind option at all - it'll default to the safest option (right now it's node).

Props merging order

The resulting props of a field are a merge of the props that uniforms provide, the ones coming from the bridge (schema) and finally the actual field props. For the exact ordering, please refer to the source of useField hook. Overall, it looks as follows:

  1. uniforms props (e.g., changed, onChange, value).
  2. uniforms state (as defined in context data).
  3. bridge props (depending on the schema)
  4. field props (only when rendered directly)

That's important, as using empty values in the schema or field props, like undefined, will be merged as well. See #1094 for more context as well as an example of a potential pitfall.

changedKeys

Returns an array of changed keys between valueA and valueB, where root is the root key. For examples see changedKeys tests.

import { changedKeys } from 'uniforms';

changedKeys('a', { b: 1, c: 2 }, { b: 1 }); // ['a', 'a.c']

filterDOMProps

Removes all uniforms-related props, registered with filterDOMProps.register. Use it in all places where you'd like to pass all unrelated props down and useField or connectField provide you with the props.

import { filterDOMProps } from 'uniforms';

const filteredProps = filterDOMProps(props);

Custom props registration

It's often the case that your custom components will have a bunch of known properties, like locale or userType. To ease the process of using them across the project, you can register them to make filterDOMProps remove them as well. For example, SimpleSchemaBridge registers all of the SimpleSchema-specific options.

import { filterDOMProps } from 'uniforms';

filterDOMProps({ example: 42 }); // { example: 42 }
filterDOMProps.registered.includes('example'); // false
filterDOMProps.register('example');
filterDOMProps.registered.includes('example'); // true
filterDOMProps({ example: 42 }); // {}

As filterDOMProps is fully typed, if you'd like to make it work with TypeScript, you have to extend the FilterDOMProps interface as well.

declare module 'uniforms' {
interface FilterDOMProps {
propA: never;
propB: never;
}
}

filterDOMProps.register('propA', 'propB');

joinName

Safely joins partial field names. If you create a custom field with subfields, do use joinName instead of manually concatenating them. It ensures that the name will be correctly escaped if needed.

import { joinName } from 'uniforms';

joinName('array', 1, 'field'); // 'array.1.field'
joinName('object', 'nested.property'); // 'object.nested.property'

If the first argument is null, then it returns an array of escaped parts.

import { joinName } from 'uniforms';

joinName(null, 'array', 1, 'field'); // ['array', '1', 'field']
joinName(null, 'object', 'nested.property'); // ['object', 'nested', 'property']

If the field name contains a dot (.) or a bracket ([ or ]), it has to be escaped with ["..."]. If any of these characters is not escaped, joinName will not throw an error but its behavior is not specified. The escape of any other name part will be stripped.

joinName(null, 'object["with.dot"].field'); // ['object', '["with.dot"]', 'field']
joinName('object["with.dot"].field'); // 'object["with.dot"].field'

joinName(null, 'this["is"].safe'); // ['this', 'is', 'safe']
joinName('this["is"].safe'); // 'this.is.safe'

For more examples check joinName tests.

randomIds

Generates random ID, based on given prefix. Use it, if you want to have random but deterministic strings. If no prefix is provided, a unique uniforms-X prefix will be used generated.

import { randomIds } from 'uniforms';

const randomId1 = randomIds();
randomId1(); // uniforms-0000-0000
randomId1(); // uniforms-0000-0001
randomId1(); // uniforms-0000-0002

const randomId2 = randomIds();
randomId2(); // uniforms-0001-0000
randomId2(); // uniforms-0001-0001
randomId2(); // uniforms-0001-0002

const randomId3 = randomIds('prefix');
randomId3(); // prefix-0000
randomId3(); // prefix-0001
randomId3(); // prefix-0002

useForm

A direct way of accessing the context data:

import { useForm } from 'uniforms';

function Example() {
const context = useForm();
}

useField

A hook version of connectField. It receives three arguments: field name (string), field props (object), and optional options.

function Example(props) {
const [fieldProps, context] = useField(props.name, props, options);
return <input {...filterDOMProps(fieldProps)} />;
}

The table below lists all available options:

NameTypeDefaultDescription
absoluteNamebooleanfalseWhether the field name should be treated as a top-level one, ignoring parent fields.
initialValuebooleantrueInitial value check. If true, then after the first render the default value is set as value if no value is provided (undefined).

Using useField allows you to create components that combine values of multiple fields:

import { useField } from 'uniforms';

function ArePasswordsEqual() {
const [{ value: passwordA }] = useField('passwordA', {});
const [{ value: passwordB }] = useField('passwordB', {});
const areEqual = passwordA === passwordB;
return <div>{`Passwords are ${areEqual ? 'equal' : 'not equal'}`}</div>;
}