gcanti / tcomb-form

Forms library for react
https://gcanti.github.io/tcomb-form
MIT License
1.16k stars 136 forks source link

Validation intersection #288

Closed skrobek closed 8 years ago

skrobek commented 8 years ago

Hi,

Im trying to build a validation based on a config. Let's say that we have an input which can accept string (min length 3, max length 10), based on this example: https://github.com/gcanti/tcomb-validation#intersections

First define validators subtypes:

const MaxLength = t.subtype(t.String, (n) => n.length < 10, 'MaxLength');
MaxLength.getValidationErrorMessage = (value, path, context) => {
  return 'Value can't be longer than 10.';
};

const MaxLength = t.subtype(t.String, (n) => n.length > 3);
MaxLength.getValidationErrorMessage = (value, path, context) => {
  return 'Value can't be shorter than 3.';
};

Then fields configuration types:

const customRules = t.intersection([MaxLength, MinLength);
const customValidation = t.refinement(t.String, customRules);

// Output
const fields = t.struct({
   stringField: customValidation
})

What I have noticed, that in the console I can see validation messages:

Uncaught TypeError: [tcomb] Invalid value "a" supplied to MaxLength & {String | <function1>}

So the validation works fine. The problem is that I can't see any error in the input form. There is no calss "error" and errorMessage it's not visible. I know that I can use one validator for this example but It's only for showcase purposes. Let's say that we want to mix very different predicates.

Can you please check this case or point me where I made a mistake?

gcanti commented 8 years ago

Hi,

So the validation works fine

No, what you are reporting is the message caused by a failing assert, a correct refinement definition would be:

// invalid type definition
const customValidation = t.refinement(t.String, customRules) // customRules is a type, not a predicate

// ok
const customValidation = t.refinement(t.String, customRules.is)

Still you can't get the correct error messages because intersections are not supported by tcomb-form at the moment.

skrobek commented 8 years ago

@gcanti Ok I got it. Is there any other way to add few validators to one field? Maybe union?

gcanti commented 8 years ago

Best bet atm is to define a single refinement type:

const max = (s) => s.length < 10
const min = (s) => s.length > 3

const MinMax = t.refinement(t.String, (s) => min(s) && max(s), 'MinMax')

MinMax.getValidationErrorMessage = (value) => {
  if (!value) {
    return 'Required'
  }
  if (!min(value)) {
    return 'Value can\'t be shorter than 3.'
  }
  if (!max(value)) {
    return 'Value can\'t be longer than 10.'
  }
}
skrobek commented 8 years ago

@gcanti Thank you for help.