gcanti / tcomb-form

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

validation issues with custom list template #196

Closed danieljuhl closed 9 years ago

danieljuhl commented 9 years ago

I have encountered an issue with this.refs.form.getValue() triggering validation on a custom List template, which has a nested structure, where the values is flattened before returned back in getValue().

Uncaught TypeError: Cannot read property 'validate' of undefined

The errors occurs here:

List.prototype.validate = function validate() {
    var value = [];
    var errors = [];
    var hasError = false;
    var result = undefined;

    for (var i = 0, len = this.state.value.length; i < len; i++) {
      result = this.refs[i].validate(); // <---- RIGHT HERE
      errors = errors.concat(result.errors);
      value.push(result.value);
    }
...

How do I assign a correct ref to each of my entries in the nested structure, or how to ignore this validation?

danieljuhl commented 9 years ago

this.state.value contains an array of strings (the correct values), but this.refs is empty, and therefore failing.

gcanti commented 9 years ago

The List factory expects an array of sub-factories, one for each element in this.state.value. You can override this behaviour defining a custom factory:

class MyList extends t.form.List {

  validate() {

    return new t.ValidationResult({
      errors: [], // <= your custom validation logic here...
      value: this.state.value
    });

  }

}

var options = {
  factory: MyList
};

var Schema = t.list(t.String);

var App = React.createClass({

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

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

});
danieljuhl commented 9 years ago

Thanks - that was the right direction. I got it working now.