---
name: Validator
menu: Components
---

# Validator
Validator会遍历其所有层级的带有data-patterns属性的表单子元素，通过HOC的方式将其变得可校验化

import Validator from './index'
import './style/index.scss'
import { Form, FormRow, Label } from '../form/index'
import Input from '../input/index'
import { Radio, RadioGroup } from '../radio/index'
import Dropdown from '../dropdown/index'
import Datepicker from '../datepicker/index'
import Button from '../button/index'
import Message from '../message/index'
import { Playground, Props } from 'docz'

### 表单元素校验属性

| 属性 | 说明 | 类型 | 默认值 |
| :--- | :--- | :--- | :--- |
| data-patterns | 校验模式，详见说明 | `array` | `undefined` |
| data-trigger | 校验时机，传入组件支持的事件prop | `string/array` | `['onChange', 'onBlur']` |
| data-checking | 传入false关闭校验 | `bool` | `undefined` |
| data-required | 表单是否必填 | `bool` | `undefined` |
| data-required-msg | 自定义必填时提示文案 | `string` | `undefined` |
| data-tips | 默认提示文案，info类型 | `string` | `undefined` |
| data-placer | 表单校验结果的回调，当此属性存在时，表单校验信息默认不展示 | `function` | `undefined` |
| data-prefix | 表单校验化后，会被im-validator-enhancer包裹，可在表单前增加前缀元素 | `React Element` | `undefined` |
| data-suffix | 表单校验化后，会被im-validator-enhancer包裹，可在表单后增加后缀元素 | `React Element` | `undefined` |

### Validator APIs
| 方法 | 说明 | 类型 |
| :--- | :--- | :--- |
| checkField(val, name) | 手动触发某一表单元素的校验，当val为undefined时，Validator会尝试取得表单的当前值 | Function(val: `any`, name: `string`): `undefined` |
| scrollToErrorField(idx, offset) | 滚动到第`idx`个错误的表单元素**(目前不支持offset参数)** | Function(idx: `number`, offset: `number`): `bool` |
| isAllValid | 获取当前Validator下所有表单的是否全部通过校验 | Function(): `bool` |
| isFieldValid(name) | 获取当前Validator下某个表单的校验值 | Function(): `null|bool` |
| resetField(name) | 重置当前Validator下某个表单的校验状态 | Function(): `undefined` |


## Validator Props & Methods
<Props of={Validator} />

## Basic Usage
<Playground>
{() => {
    class Example extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
        isFree: true,
        hasEndTime: 0,
        canSubmit: false
        };
        this.checkers = {
        endFlag: (val, callback) => {
            let isValid = true;
            let msg = '';
            if (!this.state.isFree && val === 0) {
            isValid = false;
            msg = '付费课必须选择课程截止日期';
            }
            callback({ isValid, msg });
        }
        };
        this.handleTypeChange = this.handleTypeChange.bind(this);
        this.handleFlagChange = this.handleFlagChange.bind(this);
        this.toggleSubmit = this.toggleSubmit.bind(this);
    }
    handleTypeChange(val) {
        this.setState({
        isFree: val === 1
        }, () => {
        return val === 1 ?
            this.validator.checkField(undefined, 'courseRight') :
            this.validator.checkField(undefined, 'coursePrice');
        });
    }
    handleFlagChange(val) {
        this.setState({
        hasEndTime: val === 1
        }, () => {
        this.validator.checkField(undefined, 'courseEndTime');
        });
    }
    toggleSubmit(val) {
        this.setState({
        canSubmit: val
        });
    }
    render() {
        return (
        <Validator
            ref={(instance) => { this.validator = instance; }}
            checkers={this.checkers}
            onValid={() => this.toggleSubmit(true)}
            onInValid={() => this.toggleSubmit(false)}
        >
            <Form horizontal={false}>
            <FormRow>
                <Label required>课程名称(使用内置校验模式)</Label>
                <Input
                name="courseName"
                placeholder="1-10个字"
                data-required
                data-patterns={[{
                    key: 'limit',
                    msg: '须在1-10个字内',
                    limit: {
                    min: 1,
                    max: 10
                    }
                }]}
                />
            </FormRow>
            <FormRow>
                <Label required>课程类型(表单联动)</Label>
                <RadioGroup
                name="courseType"
                style={{ display: 'inline' }}
                defaultValue={1}
                onChange={this.handleTypeChange}
                data-required
                data-patterns={[]}
                >
                <Radio value={1}>免费</Radio>
                <Radio value={2}>收费</Radio>
                </RadioGroup>
            </FormRow>
            {!this.state.isFree ?
                <FormRow>
                <Label required>课程价格</Label>
                <Input
                    name="coursePrice"
                    placeholder="内置校验模式"
                    data-required
                    data-patterns={[{
                    key: 'range',
                    msg: '须在1-8000元之间',
                    range: {
                        min: 1,
                        max: 8000
                    }
                    }]}
                />
                </FormRow> :
                <FormRow>
                <Label required>课程版权</Label>
                <Dropdown
                    name="courseRight"
                    options={[{
                    value: 1,
                    display: '免费提供课程版权给课堂'
                    }, {
                    value: 2,
                    display: '不提供课程版权'
                    }]}
                    style={{ width: 200 }}
                    data-required
                    data-patterns={[]}
                />
                </FormRow>}
            <FormRow>
                <Label>课程有效期(使用传入的校验模式，表单联动)</Label>
                <Dropdown
                name="courseEndFlag"
                options={[{
                    value: 1,
                    display: '课程截止时间'
                }, {
                    value: 0,
                    display: '学习有效期'
                }]}
                style={{ width: 200 }}
                onChange={this.handleFlagChange}
                data-patterns={[{
                    key: 'endFlag'
                }]}
                />
                {this.state.hasEndTime ?
                <FormRow>
                    <Label required>截止时间</Label>
                    <Datepicker
                    name="courseEndTime"
                    data-required
                    data-patterns={[]}
                    />
                </FormRow> : null}
            </FormRow>
            <Button disabled={!this.state.canSubmit}>提交</Button>
            </Form>
        </Validator>
        );
    }
    }
    return <Example />
}}
</Playground>

## msgAlign
<Playground>
{() => {
    class Example extends React.Component {
        constructor(props) {
        super(props);
    }
    render() {
        return (
        <Validator msgAlign="bottom">
            <Form inline horizontal={false}>
            <FormRow>
                <Label>Email</Label>
                <Input
                placeholder={'xxx@abc.com'}
                name="email"
                data-required
                data-patterns={[{
                    key: 'email',
                    msg: '请输入邮箱地址',
                }]}
                />
            </FormRow>
            <FormRow>
                <Label>Mobile</Label>
                <Input
                placeholder={'11位数字'}
                name="mobile"
                data-required
                data-patterns={[{
                    key: 'mobile',
                    msg: '请输入手机号码',
                }]}
                />
            </FormRow>
            <FormRow>
                <Label>An Integer</Label>
                <Input
                placeholder={'0'}
                name="integer"
                data-required
                data-patterns={[{
                    key: 'integer',
                    msg: '必须是数字',
                }]}
                />
            </FormRow>
            </Form>
            <br/>
            <Button>Submit</Button>
        </Validator>
        );
    }
    }
    return <Example />
}}
</Playground>

## onValid / onInValid
<Playground>
{() => {
    class Example extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                canSubmit: false
            };
            this.enableBtn = this.enableBtn.bind(this);
            this.disableBtn = this.disableBtn.bind(this);
            this.getFormValid = this.getFormValid.bind(this);
        }
        enableBtn() {
            this.setState({ canSubmit: true});
        }
        disableBtn() {
            this.setState({ canSubmit: false});
        }
        getFormValid() {
            alert(this.refs.validator.isAllValid());
        }
        render() {
            return (
            <Validator ref="validator" onValid={this.enableBtn} onInValid={this.disableBtn}>
                <Form>
                <FormRow>
                    <Label required>手机号</Label>
                    <Input
                    name="field1"
                    placeholder="请填写您的手机号"
                    data-required
                    data-patterns={[{
                        key: 'mobile',
                        msg: '格式不正确'
                    }]}
                    />
                </FormRow>
                <FormRow>
                    <Label>邮箱</Label>
                    <Input
                    name="field2"
                    placeholder="请填写您的邮箱"
                    data-patterns={[{
                        key: 'email',
                        msg: '格式不正确'
                    }]}
                    />
                </FormRow>
                <FormRow>
                    <Label>生日</Label>
                    <Datepicker
                    name="field3"
                    data-patterns={[]}
                    />
                </FormRow>
                <FormRow>
                    <Label required>性别</Label>
                    <RadioGroup
                    name="field4"
                    data-required
                    data-patterns={[]}
                    >
                    <Radio value="0">男</Radio>
                    <Radio value="1">女</Radio>
                    </RadioGroup>
                </FormRow>
                <Button type="button" disabled={!this.state.canSubmit}>提交</Button>
                <Button type="button" onClick={this.getFormValid}>API: isAllValid()</Button>
                </Form>
            </Validator>
            );
        }
        }
        return <Example />
}}
</Playground>

## Validator APIs
<Playground>
{() => {
    class Example extends React.Component {
        constructor(props) {
            super(props);
            this.scroll = this.scroll.bind(this);
            this.alertResult = this.alertResult.bind(this);
            this.resetField = this.resetField.bind(this);
        }
        scroll () {
            this.refs.validator.scrollToErrorField(0);
        }
        alertResult () {
            alert(this.refs.validator.isFieldValid('field'));
        }
        resetField () {
            this.refs.validator.resetField('field');
        }
        render() {
            return (
            <Validator ref="validator">
                <Input
                name="field"
                placeholder="YYYY-MM-DD"
                data-required
                data-patterns={[{
                    key: 'date',
                    msg: '请输入日期'
                }]}
                />
                <br />
                <Button onClick={this.scroll}>scrollToErrorField</Button>
                <Button onClick={this.alertResult}>isFieldValid</Button>
                <Button onClick={this.resetField}>resetField</Button>
            </Validator>
            );
        }
    }
    return <Example />
}}
</Playground>

##
# enhancer

## Prefix / Suffix
<Playground>
    <Validator>
        <Input
          name="field"
          data-prefix="I am a prefix "
          data-suffix={<span> I am a suffix</span>}
          data-required
          data-patterns={[{
            key: 'email',
            msg: '请输入邮箱地址'
          }]}
        />
    </Validator>
</Playground>

## 默认提示：data-tips
<Playground>
    <Validator>
        <Input
        placeholder="Try data-tips"
        name="required-msg"
        data-required
        data-tips="默认提示"
        data-patterns={[]}
        />
    </Validator>
</Playground>

## 自定义必填提示：data-required-msg
<Playground>
    <Validator>
        <Input
            placeholder={'Try data-required-msg'}
            name="data-tips"
            data-required
            data-required-msg="该选项不能为空，请输入"
            data-patterns={[]}
            />
    </Validator>
</Playground>

## 自定义提示信息位置: data-placer
<Playground>
{() => {
    class Example extends React.Component{
        constructor(props) {
            super(props);
            this.state = {
            msgEl: null
            };
            this.showErrMsg = this.showErrMsg.bind(this);
        }
        showErrMsg(data) {
            console.log(data);
            this.setState({
            msgEl: data.msgEl
            });
        }
    render() {
        return (
        <Validator>
            <span> {this.state.msgEl}</span>
            <Input
                placeholder="Try data-placer"
                name="field2"
                data-required
                data-placer={this.showErrMsg}
                data-patterns={[{
                key: 'email',
                msg: '请输入邮箱地址'
                }]}
            />
            <span> {this.state.msgEl}</span>
        </Validator>
        );
    }
    }
    return <Example />
}}
</Playground>

## 自定义校验时机: data-trigger
<Playground>
    <Validator>
        <Input
          name="field"
          placeholder="onChange Trigger"
          data-required
          data-trigger="onChange"
          data-patterns={[{
            key: 'email',
            msg: '请输入邮箱地址'
          }]}
        />
        <div style={{ height: '10px' }}> </div>
        <Input
          name="field2"
          placeholder="onBlur Trigger"
          data-required
          data-trigger="onBlur"
          data-patterns={[{
            key: 'email',
            msg: '请输入邮箱地址'
          }]}
        />
    </Validator>
</Playground>

## Check On / Off
<Playground>
{() => {
    class Example extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isChecking: true
        };
        this.toggleChecking = this.toggleChecking.bind(this);
    }
    toggleChecking() {
        this.setState({
        isChecking: !this.state.isChecking
        });
    }
    render() {
        return (
        <Validator>
            <p> The check is {this.state.isChecking ? 'on': 'off'} </p>
            <Input
            name="field"
            placeholder="Try data-checking"
            data-checking={this.state.isChecking}
            data-patterns={[{
                key: 'limit',
                msg: '须在5-50个字内',
                limit: {
                min: 5,
                max: 50
                }
            }]}
            />
            <br />
            <Button onClick={this.toggleChecking}>toggle校验</Button>
        </Validator>
        );
    }
    }
    return <Example />
}}
</Playground>


