vazco / uniforms

A React library for building forms from any schema.
https://uniforms.tools
MIT License
1.94k stars 239 forks source link

`SelectField` in tag mode doesn't show error massage #985

Open danyhiol opened 3 years ago

danyhiol commented 3 years ago

This is a follow-up to this issue. When using tag mode with SelectField with antd, the field is validated, but the validation message is not shown as an inline error below the field. Please refer to the link for details.

"uniforms": "^3.5.1",
"uniforms-antd": "^3.5.1",
"uniforms-bridge-simple-schema-2": "^3.5.1",
"react": "^17.0.2",
"antd": "^4.16.8",
radekmie commented 3 years ago

Hi @danyhiol, and sorry for the delay. Could you create a reproduction using our CodeSandbox template? It'd let us check it much faster.

danyhiol commented 3 years ago

Here is a simple reproduction link.

radekmie commented 3 years ago

Thanks! So, from what I can see, the problem is that these errors look like this:

[
  { "name": "activities.0", "value": "x", "type": "minString", "min": 10, "message": "Activities must be at least 10 characters" },
  { "name": "activities.1", "value": "xxxxxxxxxx", "type": "regEx", "regExp": /*...*/, "message": "Activities must be a valid email address" }
]

So the problem is that these are technically not errors of this component but its children. It's incorrect though, as it's responsible for these values. I'm not sure how to proceed on this one, as making these errors available to the parent field will break the rest, i.e., ListField.

As a workaround, you can create a custom SelectField that extracts these errors itself.

radekmie commented 2 years ago

(We've had a team discussion about this issue, and here are the notes.)

radekmie commented 2 years ago

Here's a proof of concept of the error extraction:

const context = useField(props.name, {}, { absoluteName: true })[1];
const length = Array.isArray(props.value) ? props.value.length : 0;
const error = Array.from({ length }).reduce(
  (error, _, field) =>
    error ??
    context.schema.getError(joinName(props.name, field), context.error),
  props.error,
);

However, it requires an additional useField in the field component, that I don't really like. It is a start, though.