uniforms icon indicating copy to clipboard operation
uniforms copied to clipboard

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

Open danyhiol opened this issue 3 years ago • 5 comments

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",

danyhiol avatar Jul 21 '21 18:07 danyhiol

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

radekmie avatar Jul 30 '21 06:07 radekmie

Here is a simple reproduction link.

danyhiol avatar Jul 30 '21 13:07 danyhiol

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 avatar Jul 30 '21 15:07 radekmie

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

  • We won't provide any further API for the childrenErrors. If needed, one can use bridge.getSubfields + bridge.getError/bridge.getErrorMessage.
  • We'll implement that for the built-in SelectFields (by rendering the first error).

radekmie avatar Dec 10 '21 10:12 radekmie

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.

radekmie avatar Feb 28 '22 14:02 radekmie