npm package: @sinoui/forms
Description: sinoui表单
Author: JackingLiu
Latest version: 0.1.31

# @sinoui/forms

> sinoui 表单

sinoui-form 使用[formik](https://github.com/jaredpalmer/formik)管理表单状态，采用[sinoui-components](http://218.240.159.110:10080/newoa/sinoui-components)实现表单 UI。它能方便的在 React 项目中构建出表单。

## Roadmap

### 表单项组件

* [x] TextInput
* [x] Select
* [x] Radio / RadioGroup
* [x] Checkbox / CheckboxGroup
* [x] FormText
* [ ] DatePicker
* [ ] TimePicker

## 基本用法

几个核心组件：

* `Form` - 表单
* `FormItem` - 表单项，负责渲染  表单标题、输入框、错误提示、帮助性提示等。
* `Label` - 表单标题。
* `Field` - 表单域。
* `TextInput`、`Radio`、`RadioGroup`... - 输入框，具体的表单域。这些输入框自动与表单绑定。

```javascript
import React from 'react';
import Form, {
  FormItem,
  Label,
  TextInput,
  FormState,
  RadioGroup,
  Radio,
} from 'sinoui-form';
import LoadingButton from 'sinoui-components/LoadingButton';

const Exmaple = () => (
  <Form
    onSubmit={(values, { setSubmitting }) => {
      callRemoteApi(values).then(
        () => setSubmitting(false),
        (error) => {
          setSubmitting(false);
          setErrors(transformMyApiErrors(errors));
        },
      );
    }}
  >
    <FormItem>
      <Label>姓名</Label>
      <TextInput name="userName" required maxLength={50} />
    </FormItem>
    <FormItem>
      <Label>性别</Label>
      <RadioGroup name="sex">
        <Radio>男</Radio>
        <Radio>女</Radio>
      </RadioGroup>
    </FormItem>
    <FormItem>
      <Label>年龄</Label>
      <TextInput type="number" name="age" />
    </FormItem>
    <FormState>
      {({ isSubmitting }) => (
        <LoadingButton raised color="primary" loading={isSubmitting}>
          提交
        </LoadingButton>
      )}
    </FormState>
  </Form>
);
```

## 在表单外提交

```javascript
import { Form, FormItem, TextInput, FormState } from 'sinoui-form';

function submitForm(formik) {
  formik.setSubmitting(true);
  callRemoteApi(values).then(
    () => setSubmitting(false),
    error => {
      setSubmitting(false);
      setErrors(transformMyApiErrors(errors));
    },
  );
}

function FormExample() {
  return <div>
  <Form name="exampleForm">
    <FormItem>
      <Label>姓名</Label>
      <TextInput name="userName" required />
    </FormItem>
  </Form>
  <FormState formName="exampleForm">
    {formik => <LoadingButton
      color="primary"
      raised
      disabled={!formik.isValid}
      onClick={submitForm}
    >在表单外提交表单</LoadingButton>}
  </FormState>
}
```

## 表单域 `<Field />`

表单域`<Field />`会自动地将输入框与`<Form />`挂钩。它使用`name`属性来匹配表单状态。`<Field />`默认使用`<input />`元素渲染输入框。可以使用`component`或者`render`属性指定其他类型的输入框元素。

```javascript
import React from 'react';
import Form, { Field } from 'sinoui-form';
import TextInput from 'sinoui-components/TextInput';

const Example = () => (
  <Form>
    <Field name="userName" />
    <Field name="firstName" component={TextInput} />
    <Field
      name="lastName"
      render={({ field /* _form */ }) => (
        <TextInput {...field} placeholder="lastName" />
      )}
    />
  </Form>
);
```

### 表单域验证

```javascript
import React from 'react';
import Form, { Field } from 'sinoui-form';

const Example = () => (
  <Form>
    // 必填验证：
    <Field name="userName" required />
    // 最小值、最大值验证
    <Field name="age" min={10} max={30} />
    // 最大长度验证
    <Field name="userName" maxLength={10} />
    // 自定义表单域验证逻辑
    <Field
      name="userName"
      validate={(value) =>
        value &&
        !/^\d{11}$/.test(value) &&
        '请输入正确的手机号码，如13466666666'
      }
    />
  </Form>
);
```