# form

* 作者：liuduan
* 邮箱：liuduan.05.05@163.com
* 版本：**`1.0.2`**

## 介绍

_表单组件，包含input、checkbox、radio、select、textarea、agreement、switch、validate、valiate.rule、autoclear_

---

## 安装

`lm-*` 组件使用 `npm` 进行管理，命名空间统一为 `lm-`，请使用以下命令进行组件安装。

```
npm i lm-form --save
```

- 如果你还没有安装 `npm`，可通过以下方式进行 [安装](https://nodejs.org/en/download/)。
- 安装cnpm `npm install -g cnpm --registry=https://registry.npm.taobao.org`


---

## 使用

### 样例文档

- 用于input输入过程中校验

```javascript
    // 只需调用Sumit组件，无需引用Validate
    // onClick提交表单，参数为校验值系列化对象
    // onError用于错误信息提示
    // disabled:默认true必须所有必填项填完才能改为false
    // input要使用InputValidate组件
    <Submit 
        onClick={this.onValidateSubmit.bind(this)} 
        onError={this.onValidateError.bind(this)} 
        disabled={disabled}>
        input 验 证 提 交
    </Submit>

    // valiate.type === 'submitValidate'用于区分input输入过程中校验还是sumit提交时校验，默认值为'inputValidate'
    <InputValidate
        label="姓名"
        name="inputvalidate1"
        type="text"
        placeholder="validate input"
        value={this.state.inputValidate1}
        onChange={(val) => this.handleInputValidateChange(val, 'inputValidate1')}
        validate={{
            rule: /^\d+$/,
            param: [],
            requireMsg: '该字段必填',
            errMsg: '请输入数字1',
            type: 'submitValidate'
        }}
        required
    />
```

- `validate`-用于submit提交过程中校验
```javascript
    // 使用高阶组件ValidateHoc获取校验属性
    ValidateHoc(App);
    // submit校验
    this.props.formValidate(validateArr)
            .then(query => {
                // query为提交表单插叙字符串
                console.log(query)
            })
            .catch(err => {
                // 可执行toast，err为错误message
                console.log(err)
            })
    // onBlur校验
    const { isValid, message } = this.props.inputValidate({ value, rule, param, required });
    /* 
		根据·isValid·判断input是否校验通过，包括 required && validate rule 校验，true 为通过，false 为不通过
		根据·message·返回信息 
			如果为 'required' 可执行toast提示改项为必须项，
			如果为 其他 可执行toast提示错误信息message
		*/
```

- `validateArr`

```javascript
    let validateArr = [
            {
                ref: this.inputRef,
                name: 'input',
                value: text,
                // rule: 可以为字符串、数组、正则，字符串或数组必须在rule.js中属性，数组意为检验符合多个规则
                rule: ['idNumber', 'idcardUnique'],
                //rule: /\d+/,
                param: [0, 2],
                err: 'textErr',
                required: true,
                errMsg: 'input错误',
                requireMsg: 'input必填'
            }, {
                name: 'checkbox',
                value: checkbox,
                required: true
            }
        ];
```

### 使用
最少配置参数为：

- `InputValidate`组件（input输入过程中校验）

```javascript
    <InputValidate
        type="text"
        placeholder="validate input"
        value={this.state.inputValidate}
        onChange={(val) => this.handleInputValidateChange(val, 'inputValidate')}
        validate={{
            rule: /^\d+$/, 
            param: [],
            requireMsg: '该字段必填',
            errMsg: '请输入数字'
        }}
        required
    />
```

- `Input`组件(可控)使用

```javascript
<Cell>
    <div className="lm-cell-label">Input</div>
    <CellBody>
        <Input
            ref={el => this.inputRef = el}
            type="text"
            value={this.state.text}
            err={this.state.textErr}
            onChange={val => this.handleInputchange(val, 'text')}
            onBlur={val => this.handlerBlur({ value: val, required: true })}
            placeholder="please input"
        />
    </CellBody>
    <CellFooter>元</CellFooter>
</Cell>
```

- `Input`组件(非控)使用

```javascript
<Cell>
    <div className="lm-cell-label">Smscode</div>
    <CellBody>
        <Input
            type="text"
            defaultValue="input"
            placeholder="please smscode"
        />
    </CellBody>
    <Smscode style={{ paddingTop: 0, paddingBottom: 0 }}>开启倒计时</Smscode>
</Cell>
```
- `Checkbox`组件(可控)使用
```javascript
<Checkboxgroup
    data={data}
    inline={false}
    name="checkbox"
    checked={this.state.checkbox}
    onChange={this.handleChange} />
```

- `Checkbox`组件(非控)使用
```javascript
<Cell>
    <div className="lm-cell-label">Checkbox</div>
    <CellBody>
        <Checkboxgroup data={data} defaultChecked={false} />
    </CellBody>
</Cell>
```

- `Redio`组件(可控)使用
```javascript
<Radiogroup
    data={data}
    inline={false}
    name="radio"
    checked={this.state.radio}
    onChange={this.handleChange} />
```

- `Redio`组件(非控)使用
```javascript
<Cell>
    <div className="lm-cell-label">Radio</div>
    <CellBody>
        <Radiogroup
            name="radio-inline"
            data={data}
            defaultChecked={false} />
    </CellBody>
</Cell>
```

- `Switch`组件使用
```javascript
<Switch
    label={'switch'}
    checked={this.state.switchinput}
    onChange={this.handleChange} />
```

- `Agreement`组件使用
```javascript
<Agreement
    label={'同意'}
    checked={this.state.agree}
    onChange={this.handleChange}>
    <a>《车分期征信查询授权书》</a>
    <a>《车分期征信查询授权书》</a>
    <a>《车分期征信查询授权书》</a>
    <a>《车分期征信查询授权书》</a>
</Agreement>
```
- `Select`组件使用
```javascript
<Cell>
    <div className="lm-cell-label">Select</div>
    <CellBody>
        <Select
            name="select"
            value={this.state.select}
            placeholder="选我"
            onChange={this.handleChange}
            data={data}
        />
    </CellBody>
    <CellFooter direction="down" />
</Cell>
```

- `Textarea`组件使用
```javascript
<Cell>
    <Textarea
        name="textarea"
        value={this.state.textarea}
        onChange={this.handleTextareaChange}
        maxLength={50} />
</Cell>
```


### Input配置参数

| Prop | Type | Default | Description |
| ---- |:----:|:-------:| :----------:|
| **`className`** | `string` | `undefined` | 自定义类名 |
| **`placeholder`** | `string` | `'请输入'` | 提示信息 |
| **`defaultValue`** | `string` | `''` | 默认值，用于非控制input |
| **`value`** | `string || number` | `''` | 值，配合onChange使用 |
| **`type`** | `string` | `'text'` | input类型 |
| **`err`** | `bool` | `false` | 判断输入是否符合错误，错误：true，正确：false |
| **`onChange`** | `function` | `'onChange(){}` | onchange事件回调 |
| **`onFocus`** | `function` | `onFocus(){}` | onfocus事件回调 |
| **`onBlur`** | `function` | `'onBlur(){}` | onblur事件回调 |
| **`refName`** | `string` | `'inputRef'` | 原生ref属性值，可通过container中的ref.inputRef获取原生input的ref |
| **`maxLength`** | `number` | `-` | 长度限制 |
| **`useClear`** | `bool` | `true` | true：使用自动清除，false：不使用 |

- <em>其他input支持属性Input组件都可支持</em>
---

### InputVaidate配置参数

| Prop | Type | Default | Description |
| ---- |:----:|:-------:| :----------:|
| **`hintClassName`** | `string` | `undefined` | 自定义类名 |
| **`validate`** | `object` | `{}` | 验证参数对象 |
| **`required`** | `bool` | `false` | 是否必填 |
| **`onChange`** | `function` | `() => {}` | 回调 |
| **`onFocus`** | `function` | `() => {}` | 回到 |
| **`onBlur`** | `function` | `() => {}` | 回调 |
| **`label`** | `string` | `` | 左侧label文案 非必填 |

- <em>其他Input支持属性InputValidate组件都可支持</em>
---

- <em>其他input支持属性Input组件都可支持</em>
---

### Checkbox/Radio/Switch/Agreement配置参数

| Prop | Type | Default | Description |
| ---- |:----:|:-------:| :----------:|
| **`className`** | `string` | `undefined` | 自定义类名 |
| **`inline`** | `bool` | `true` | 多个checkbox是否在一行显示 |
| **`defaultChecked`** | `bool` | `undefined` | 默认是否选中，用于非控制checkbox |
| **`checked`** | `bool` | `undefined` | 是否选中，配合onChange使用 |
| **`label`** | `string | number | element` | `''` | label |
| **`disabled`** | `bool` | `false` | 禁用 |
| **`onChange`** | `function` | `'onChange(){}` | onchange事件回调 |

---


## Checkboxgroup配置参数

| Prop | Type | Default | Description |
| ---- |:----:|:-------:| :----------:|
| **`data`** | `array isRequired` | `[]` | 数据 |
| **`checked`** | `array` | `undefinde` | 多选选中value值数组 |
| **`disabled`** | `bool` | `false` | 禁用，如果disabled不同，可用过data属性传入 |
| **`name`** | `string` | `''` | checkbox name，如果name不同，可用过data属性传入name |

## Radiogroup配置参数

| Prop | Type | Default | Description |
| ---- |:----:|:-------:| :----------:|
| **`data`** | `array isRequired` | `[]` | 数据 |
| **`checked`** | `any` | `undefinde` | 单选选中value值 |
| **`disabled`** | `bool` | `false` | 禁用，如果disabled不同，可用过data属性传入 |## Checkboxgroup配置参数

- <em>其他Checkbox支持属性Checkboxgroup组件都可支持，其中label、value属性必须在data中传入</em>
- <em>其他Radio支持属性Radiogroup组件都可支持，其中label、value属性必须在data中传入</em>
- <em>data 格式, 属性名不能更改</em>

```javascript
const data = [
    { value: 0, label: 'Ph.D.' },
    { value: 1, label: 'Bachelor' },
    { value: 2, label: 'College', name: 'a', disabled: false }
]
```
---

### Textarea配置参数

| Prop | Type | Default | Description |
| ---- |:----:|:-------:| :----------:|
| **`className`** | `string` | `undefined` | 自定义类名 |
| **`placeholder`** | `string` | `'请输入'` | 提示信息 |
| **`defaultValue`** | `string` | `''` | 默认值，用于非控制input |
| **`value`** | `string || number` | `undefined` | 值，配合onChange使用 |
| **`err`** | `bool` | `false` | 判断输入是否符合错误，错误：true，正确：false |
| **`maxLength`** | `number` | `50` | 最大输入字数 |
| **`showCounter`** | `bool` | `true` | 是否显示字数提示，默认显示 |
| **`onChange`** | `function` | `onChange(){}` | onchange事件回调 |
| **`onFocus`** | `function` | `onFocus(){}` | onfocus事件回调 |
| **`onBlur`** | `function` | `onBlur(){}` | onblur事件回调 |
| **`useClear`** | `bool` | `true` | true：使用自动清除，false：不使用 |
- <em>其他textarea支持属性Textarea组件都可支持</em>
---

### Select单选配置参数

| Prop | Type | Default | Description |
| ---- |:----:|:-------:| :----------:|
| **`className`** | `string` | `undefined` | 自定义类名 |
| **`placeholder`** | `string` | `'请输入'` | 提示信息 |
| **`value`** | `string || number` | `''` | 选中值 |
| **`data`** | `array` | `[]` | 渲染option用数据，若不传可自定义children 作为option |
| **`disabled`** | `bool` | `false` | 禁用，如果disabled不同，可用过data属性传入 |
| **`onChange`** | `function` | `'onChange(){}` | onchange事件回调 |

- <em>其他select支持属性Select组件都可支持，但只支持单选，不支持多选</em>
- <em>data 格式</em>


### Submit配置参数

| Prop | Type | Default | Description |
| ---- |:----:|:-------:| :----------:|
| **`className`** | `string` | `undefined` | 自定义类名 |
| **`style`** | `object` | `undefinde` | 自定义样式 |
| **`type`** | `string` | `''` | button-type |
| **`disabled`** | `book` | `true` | 必须在所有必填项有之后才可解除禁用 |
| **`onClick`** | `function` | `onClick(){}` | 提交表单回调，参数为验证表单序列化对象 |
| **`onError`** | `function` | `'onError(){}` | 错误信息事件回调，参数为错误信息 |


```javascript
const data = [
    { value: 0, label: 'Ph.D.' },
    { value: 1, label: 'Bachelor' },
    { value: 2, label: 'College', disabled: false }
]
```
---

### validate.rule 校验规则

| Prop | Type | Default | Description | Message |
| ---- |:----:|:-------:| :----------:| :----------:|
| **`password`** | `string` | `-` | 密码校验 | `请填写${param[0]}-${param[1]}位字母、数字` |
| **`equal`** | `string` | `-` | 两次输入是否一致校验 | `两次输入${param[1]}不一致`<br>备注：`param[0]`为同value比较的值 | 
| **`age`** | `string` | `-` | 年龄校验 | `对不起，您的年龄不符合准入要求` |
| **`idNumber`** | `string` | `-` | 身份证号校验 | `请填写正确的身份证号` |
| **`digital`** | `string` | `-` | 大于0数字，两个小数点 | `请填写大于0数字(如：8.25)` | `请填写${param[0]}-${param[1]}的整数` |
| **`intRange`** | `string` | `-` | 整数范围 | `请填写${param[0]}-${param[1]}的整数` | 
| **`digitalRange`** | `string` | `-` | 金额数字范围 | `还款金额请填写${param[0]}-${param[1]}的数字` | 
| **`number`** | `string` | `-` | 正整数-位数范围校验 | `请填写${param[0]}-${param[1]}位正整数` | 
| **`inviteCode`** | `string` | `-` | 邀请码数字范围校验 | `请填写${param[0]}-${param[1]}位数字` | 
| **`name`** | `string` | `-` | 姓名校验，不带'·' | `请填写${param[0]}-${param[1]}个中文` | 
| **`nameAddDot`** | `string` | `-` | 姓名校验，带'·' | `请填写${param[0]}-${param[1]}个中文` | 
| **`areacode`** | `string` | `-` | 区号校验 | `请填写正确的区号` |
| **`telephone`** | `string` | `-` | 固定电话校验 | `请填写正确的区号` 或 `请填写正确的固话`<br>备注：`param[0]` 为区号 |
| **`mobilephone`** | `string` | `-` | 手机号码校验 | `请填写正确的手机号` |
| **`length`** | `string` | `-` | 字符长度校验 | `请填写${param[0]}-${param[1]}个字符` | 
| **`bankCard`** | `string` | `-` | 银行卡检验，允许0开头 | `请填写正确的银行卡号` |
| **`creditCard`** | `string` | `-` | 信用卡号校验 | `请填写正确的信用卡号` |
| **`consistency`** | `string` | `-` | 两个值不能相同校验 | `${param[1]}与${param[2]}不能相同`<br>备注：`param[0]`为同value比较的值 |
| **`idcardUnique`** | `string` | `-` | 通过后台同步请求验证身份证号是否被注册过 | `该身份证号已注册！` |
| **`lt`** | `string` | `-` | 可用余额校验 | `可用余额${param[0]}<${param[1]}，暂不能提现！` |
| **`digitalRangeTwo`** | `string` | `-` | 数字范围，提示数字单位为万 | `请填写${param[0]}万-${param[1]}万的数字` |
| **`imageCode`** | `string` | `-` | 图形验证码校验 | `请填写${param[0]}位图形验证码` |
| **`smsCode`** | `string` | `-` | 短信验证码校验 | `请填写${param[0]}位短信验证码` |
| **`income`** | `string` | `-` | 月收入校验，特殊处理 | `收入金额过小或格式错误(最多两位小数)` |
| **`VIN`** | `string` | `-` | 车架号校验 | `请填写正确的车架号` |
| **`carPlateNumber`** | `string` | `-` | 车牌号校验 | `请输入正确的车牌号` |
| **`dateNum`** | `string` | `-` | 无链接符日期校验 | `请填写${param[0]}-${param[1]}位数字` |
| **`limitDigital`** | `string` | `-` | 车辆成交价校验 | `请填写${param[0]}元-${param[1]}元的数字` |
| **`email`** | `string` | `-` | 邮箱校验 | `请填写正确的邮箱格式` |

- <em>校验参数`param`类型为`array`</em>

---



## 注意事项

- 组件注意事项

自定义校验规则可通过，`ValidateHoc(App, rule)` 第二个参数rule传入，rule类型为对象，书写规范参考`validate.rule.js`。

`validate.rule.js` 内部已定义部分检验规则。

若想直接通过正则表达式校验，可在 this.props.formValidate(validateArr) 调用的 validateArr 中，rule直接赋值正则表达式。

- 校验函数示例

```javascript
    // 整数范围
    intRange: (value, param) => ({
        validator: new RegExp('^[1-9]\\d*$', 'g').test(value) && (parseInt(value) >= param[0]) && (parseInt(value) <= param[1]),
        message: `请填写${param[0]}-${param[1]}的整数`
    }),
```

---

## 开发调试

进入项目目录后，使用 `node` 命令启动服务

```
npm run start
```

打包发布可通过 `node` 命令执行

```
npm run build
npm publish
```

---

## 相关资料

* [lm 组件开发规范](http://)

---

## Changelog

### 0.1.0
1. init

### 0.1.1
1. 更新input样式

### 0.1.2
1. validate bugfix 

### 0.1.3
1. validata 增加`errMsg`、`requireMsg`属性，区分错误提示信息

### 0.1.4
1. 修复Input、Textarea组件readOnly时会显示autoClear的bug
2. 增加input readonly、disabled显示样式

### 0.1.5
1. 修复Input type为number类型时maxLength属性失效问题
2. 修复Input 样式bug
3. 修改Input、Textarea readOnly状态样式

### 0.1.6
1. 增加validate.rule readme
2. Input readme增加maxLength属性
3. Input 增加refName属性，用于获取原生input
4. validate.rule增加 mobilephone 手机号校验
5. validate errMsg支持array类型，用于多个rule时，不同校验规则下的错误提示信息。若errMsg为string类型，只能提示一个错误提示信息

### 0.1.7
1. 姓名校验增加自动去空格功能
2. 表单序列化时增加字符串类型自动去掉两端空格功能
3. validate.rule对param进行容错处理

### 0.1.8
1. input placehoder err时增加颜色显示
2. select、input[type=number]增加兼容火狐浏览器样式处理

### 0.1.9
1. 修复了validate中校验逻辑中的bug
2. 增加了`InputValidate`、`TextareaValidate`、`Form`组件，用于input输入中校验场景

### 0.2.0
1. 去掉了`Form`组件
2. 增加了`Submit`组件，代替之前`Form`组件
3. 增加了`InputValidate`的通用性，适用于input输入过程中校验和只在submit阶段校验两种业务场景，通过validate属性的type属性区分，type为'submitValidate'则只在提交时校验，type默认为input输入时校验。

### 0.2.1 
1. 修复了`Autoclear`组件pc端bug
2. 校验规则中增加了`dateNum`、`email`、`limitDigital`校验规则


### 0.2.3
1. 修改`Autoclear`显示样式

### 0.2.4
1. 增加`Autoclear`是否显示属性`useClear`
2. 修复`Input` value undefined值时报错问题
3. 修复`Input` number 类型可输入e问题
4. 修正无连接符日期`dateNum`校验规则

### 0.2.5
1. 修改`checkinput`组件中`label`的属性类型为字符串或数字或dom元素

### 0.2.6
1. 增加电话号码号段校验

### 0.2.7
1. 校验年龄bug修复

### 0.2.8
1. 移除includes方法
2. 修复input type number bug

### 0.2.9
1. 修改日期校验规则

### 0.2.10
1. 修改车架号校验规则

### 0.3.0
1. 升级至react-16版本

### 0.3.2
1. 修复input、textarea 组件卸载时setState bug

### 0.3.3
1. 修复input、textarea onBlur时x号一直显示bug
2. validate.js rule 兼容function

### 0.3.4
1. bugfix for validate.js rule

### 0.3.5
1. setTimeout add clearTimeout

### 0.3.6
1. 升级ui

### 0.3.7
1. agreement组件bugfix

### 0.3.8
1. agreement组件bugfix，增加uuid


### 0.3.9
1. 修改姓名校验规则

### 0.3.11
1. select bugfix

### 0.3.12
1. optimize animation


### 0.3.13
1. input and lm-cell-label style bugfix

### 1.0.0
1. modify css because new ui standard

### 1.0.1
1. modify checkbox and agreement css

### 1.0.2
1. upgrade dependency lm-cell version


---