gcanti / tcomb-form

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

pass the component options to the error option function #222

Closed gcanti closed 8 years ago

benmonro commented 8 years ago

:+1: yay! Thanks @gcanti

btw, just want reiterate how awesome tcomb & all the associated libraries are. They've been a huge help!

benmonro commented 8 years ago

Actually @gcanti this may be problematic. We are using validation on both server and client. On the server we will not have access to the entire form. We have moved our field options into a separate require so it can be shared by both, but I won't be able to create an instance of the form in our services when we do server side validation...

gcanti commented 8 years ago

Ok, let's merge only the options for now

getValidationOptions() {
  return {
    path: this.props.ctx.path,
    context: t.mixin(t.mixin({}, this.props.context || this.props.ctx.context), { options: this.props.options })
  };
}
gcanti commented 8 years ago

Released in v0.6.8 and v0.7.4

benmonro commented 8 years ago

@gcanti I'm running into an issue with running this code isomorphically. On the server I am using tcomb-validation directly since there won't be a form in that case, it's simply used to validate the data in our service. However, I'm using that same model & refinements / error messages in the client using tcomb-form. The problem I run into is that with tcomb-form, the context gives me an instance of the options for that particular field whereas in tcomb-validation it gives me whatever I pass in to validate(). so the question I have is, how can I write this code isomorphically such that I can define this once and not have to have special cases for each.

Here's an example of what I mean:

on the server i have code like this:

        let result = validate(body.data, type, options);

on the client I simply rely on tcomb-form to validate like this:

this.refs.form.validate();

however because of this I have to have the following code in my error message function in order to handle both cases.

let tcbString = tcb.String;
tcbString.getValidationErrorMessage = function (value, path, context) {
    let label = _.get(context, `fields.${path}.label`, _.get(context, 'options.label', 'field'));
    return (!value ? `${label} is required` : null);
}

as you can see I have to have a get call for the server version and a different one for the client version. I'd prefer to be able to access the label in one way...