gcanti / tcomb-form

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

How to set error messages when input changed? (v0.5.5) #153

Closed lancetw closed 9 years ago

lancetw commented 9 years ago

I like this project, but need more tips with new version / custom validation methods. setState({hasError: true}) does work well, but error message doesn't.

onChange(value, path) {
  const passField = this.refs.form.getComponent('password');

  if (passField.state.value.length < 6) {
    passField.setState({hasError: true});
    /*passField.setState({hasError: true, error: 'ERROR MESSAGE'});*/  // don't work
  }
  else {
    passField.setState({hasError: false});
  }
}
gcanti commented 9 years ago

Hi,

error is an option (it's not available in the component's state) :

https://github.com/gcanti/tcomb-form/blob/master/GUIDE.md#error-message

you can find an example here (dynamically change the form's options):

https://github.com/gcanti/tcomb-form/blob/master/GUIDE.md#rendering-options

btw you are validating the password field by hand, is there a particular reason to bypass the built-in validation system?

gcanti commented 9 years ago

With "built-in system" I mean something like this:

import React from 'react';
import t from 'tcomb-form';

const Form = t.form.Form;

const Password = t.subtype(t.Str, s => s.length >= 6);

const Type = t.struct({
  username: t.Str,
  password: Password
});

const options = {
  fields: {
    password: {
      type: 'password',
      error: 'Please type a password with at least 6 chars'
    }
  }
};

const App = React.createClass({

  onSubmit(evt) {
    evt.preventDefault();
    var value = this.refs.form.getValue();
    if (value) {
      console.log(value);
    }
  },

  render() {
    return (
      <form onSubmit={this.onSubmit}>
        <Form ref="form"
          type={Type}
          options={options}
        />
        <button className="btn btn-primary">Save</button>
      </form>
    );
  }

});

React.render(<App />, document.getElementById('app'));
lancetw commented 9 years ago

Thanks @gcanti!

It's very helpful to me. (tcomb-form does work well with server responses.)

subtype is fine, but I don't know how to "compare two field's values" and check chars length both. I really want to know how to use built-in validation system to implement it. (sometimes maybe need more complex validations.)

lancetw commented 9 years ago

Another scenario, to validate an end date field don't before start date.

gcanti commented 9 years ago

Validations are expressed as types: https://github.com/gcanti/tcomb-form/blob/master/GUIDE.md#types In your case a subtype of a struct:

function isValid(value) {
  return value.startDate <= value.endDate;
}

const Type = t.subtype(t.struct({
  startDate: t.Num, // millis
  endDate: t.Num    // millis
}), isValid);
lancetw commented 9 years ago

:+1: Thanks, validations is working (but hasError does no changed).

gcanti commented 9 years ago

Since the validation applies to a struct, hasError doesn't change for any field. You can set a global error though:

function isValid(value) {
  return value.startDate <= value.endDate;
}

const Type = t.subtype(t.struct({
  startDate: t.Num, // millis
  endDate: t.Num    // millis
}), isValid);

const options = {
  error: 'Invalid dates' // this will be displayed when the struct is invalid, see https://github.com/gcanti/tcomb-form/blob/master/GUIDE.md#error-message
};
lancetw commented 9 years ago

Thanks a lot!