jurassix / react-validation-mixin

Simple validation mixin (HoC) for React.
MIT License
283 stars 38 forks source link

Validate input in child component #28

Closed zvitek closed 9 years ago

zvitek commented 9 years ago

Hello, its possible to use validation for children components? I have the structure below and do not know how to connect. Thanks for any help

FORM Component

var Input = require('../form/input');

var CustomerDetail = React.createClass({
    mixins: [ValidationMixin, React.addons.LinkedStateMixin],
    validatorTypes:  {
        customer_name: Joi.string().required().label('Customer name')
    },
    getInitialState: function() {
        return {
            customer_name: null
        };
    },
    render: function() {
        return (
            <form method="POST" onSubmit={this.handleSubmit}>
                <Input placeholder={'Customer name'} ref='customer_name' valueLink={this.linkState('customer_name')} onBlur={this.handleValidation('customer_name')} name={'customer_name'} icon={'fa fa-home'} />
                {this.getValidationMessages('customer_name').map(this.renderHelpText)}
            </form>
        );
    }
    ...
});

INPUT Component

var Input = React.createClass({
    render: function() {
        return (
            <label htmlFor={this.props.name} className="field prepend-icon">
                <input type={this.props.type} name={this.props.name} id={this.props.name} className="gui-input" placeholder={this.props.placeholder} />
                <label htmlFor={this.props.name} className="field-icon">
                    <i className={this.props.icon}></i>
                </label>
            </label>
        );
    }
});
jurassix commented 9 years ago

What you trying to do can be done. But you need to pass the Input component a change handler to update the customer name in the Form component. That way you can validate changes in children.

Below is how I would expect it to look give you examples above:

var Input = require('../form/input');

var CustomerDetail = React.createClass({
    mixins: [ValidationMixin, React.addons.LinkedStateMixin],
    validatorTypes:  {
        customer_name: Joi.string().required().label('Customer name')
    },
    getInitialState: function() {
        return {
            customer_name: null
        };
    },
    render: function() {
        return (
            <form method="POST" onSubmit={this.handleSubmit}>
                <Input 
                  placeholder={'Customer name'} 
                  changeHandler={this.handleChange('customer_name')} 
                  validationHandler={this.handleValidation('customer_name')} 
                  value={this.state.customer_name} 
                  name={'customer_name'} 
                  icon={'fa fa-home'} >
                {this.getValidationMessages('customer_name').map(this.renderHelpText)}
               </Input>
            </form>
        );
    },
   handleChange: function(field) {
     return function(e) {
        this.state[field] = e.target.value;
        this.setState(this.state);
     }.bind(this);
  }
    ...
});
var Input = React.createClass({
   propTypes: {
     placeholder: React.PropTypes.string,
     value: React.PropTypes.string,
     name: React.PropTypes.string,
     type: React.PropTypes.string,
     icon: React.PropTypes.string,
     validationHandler: React.PropTypes.func.isRequired,
     changeHandler: React.PropTypes.func.isRequired
   },
   getDefaultProps: function() {
     return {
      type: 'text'
     };
   },
   render: function() {
        return (
            <label htmlFor={this.props.name} className="field prepend-icon">
                <input type={this.props.type} name={this.props.name} id={this.props.name} className="gui-input" placeholder={this.props.placeholder} value={this.props.value} onChange={this.props.changeHandler} onBlur={this.props.validationHandler} />
                <label htmlFor={this.props.name} className="field-icon">
                    <i className={this.props.icon}></i>
                </label>
                {this.props.children}
            </label>
        );
    }
});
zvitek commented 9 years ago

An excellent solution, thank you very much for your help and mixin! :)