jannikbuschke / formik-antd

Simple declarative bindings for Ant Design and Formik.
https://codesandbox.io/s/github/jannikbuschke/formik-antd-example
MIT License
591 stars 80 forks source link
ant-design antd declarative formik forms react

Build Status GitHub stars npm All Contributors license

Install for ant design 5 (beta)

npm i formik-antd@beta

Install for ant design 4

npm i formik-antd

formik-antd

Simple declarative bindings for Ant Design and Formik.

Core Concept

This library enriches several Ant Design components with a required name: string prop that connects them to a Formik form field. It is quite simple. Instead of importing your form components from antd, you need to import them from 'formik-antd' and set their name prop. Now the component is connected/synced with the corresponding Formik field!

The Ant Design components are feature rich and provide a lot of props to customize their visual presentation. These features and also their apis stay exactly the same. Visit their documentation to learn more.

Example:

import React from 'react'
import { Form, Input, InputNumber, Checkbox } from 'formik-antd'
import { Formik } from 'formik'

function App() {
  return (
    <Formik
      {/* default/initial values are set on the Formik container: */ }
      initialValues={{ firstName: '', age: 20, newsletter: false }}
      render={() => (
        <Form>
          {/* every formik-antd component must have the 'name' prop set: */}
          <Input name='firstName' placeholder='First Name' />
          {/* the rest of the api stays as is */}
          <InputNumber name='age' min={0} />
          <Checkbox name='newsletter'>Newsletter</Checkbox>
        </Form>
      )}
    />
  )
}

Getting started

npm install formik-antd

Add import "antd/dist/antd.css" to your index.js file or check the Advanced setup section

Core Components

Name Props
:white_check_mark: AutoComplete { name, validate?, fast? } & AutoCompleteProps
:white_check_mark: Cascader { name, validate?, fast? } & CascaderProps
:white_check_mark: Checkbox { name, validate?, fast? } & CheckboxProps
:white_check_mark: Checkbox.Group { name, validate?, fast? } & CheckboxGroupProps
:white_check_mark: DatePicker { name, validate?, fast? } & DatePickerProps
:white_check_mark: DatePicker.WeekPicker { name, validate?, fast? } & WeekPickerProps
:white_check_mark: DatePicker.RangePicker { name, validate?, fast? } & RangePickerProps
:white_check_mark: DatePicker.MonthPicker { name, validate?, fast? } & MonthPickerProps
:white_check_mark: Input { name, validate?, fast? } & InputProps
:white_check_mark: InputNumber { name, validate?, fast? } & InputNumberProps
:white_check_mark: Input.Password { name, validate?, fast? } & InputPasswordProps
:white_check_mark: Input.TextArea { name, validate?, fast? } & Input.TextAreaProps
:white_check_mark: Mentions { name, validate?, fast? } & MentionsProps
:white_check_mark: Radio.Group { name, validate?, fast? } & RadioGroupProps
:white_check_mark: Rate { name, validate?, fast? } & RateProps
:white_check_mark: Select { name, validate?, fast? } & SelectProps
:white_check_mark: Slider { name, validate?, fast? } & SliderProps
:white_check_mark: Switch { name, validate?, fast? } & SwitchProps
:white_check_mark: Table { name, fast? } & TableProps
:white_check_mark: TimePicker { name, validate?, fast? } & TimePickerProps
:white_check_mark: Transfer { name, validate?, fast? } & TransferProps
:white_check_mark: TreeSelect { name, validate?, fast? } & TreeSelectProps

Submitting and Resetting Forms

Directly under each <Formik> container a <Form> component should be placed. This component composes the functionality provided by Ant Designs (https://ant.design/components/form/) as well as Formiks (https://jaredpalmer.com/formik/docs/api/form) <Form> components:

import React from 'react'
import { Form, SubmitButton, ResetButton /* ... */ } from 'formik-antd'
import { Formik } from 'formik'

function App() {
  return (
    <Formik initialValues={/* ... */} onSubmit={/* ... */}>
      <Form>
        {/* ... */}
        <SubmitButton />
        <ResetButton />
      </Form>
    </Formik>
  )
}

The SubmitButton and ResetButton will disable automatically depending on form state. The ResetButton is enabled if the form is dirty. The SubmitButton is enabled if the form is valid or if it is not dirty and the submit count is zero. If you do want to control the disable behavior yourself you can provide the disable: boolean prop. I.e. <SubmitButton disabled={false} /> will make the button always be enabled.

Form- and Field-level Validation

Formik provides form- and field-level validation callbacks to provide validation logic. How to validate is neither part of formik nor of this library.

Form-level validation is done by setting formiks validate prop. Field-level validation is optional available on the components. Additional to the name prop formiks optional validate?: (value: any) => undefined | string | Promise<any> is added to all core components to allow field-level validation. There is one special case to be aware of when using field-level validation: When using the Form.Item component with another Antd field component, the validate prop has to be added to the Form.Item, not the input component:

<Form.Item name='firstName' validate={validator}>
  <Input name='firstName' />
</Form.Item>

Rendering Validation Feedback

Showing validation messages can be accomplished with the Form.Item component (or FormItem which is the same). It

<Form.Item name='firstName'>
  <Input name='firstName' />
</Form.Item>

FastField support

Formik allows performance optimizations through the <FastField/> component. Please read the formik docs on when to use such an optimization (usually you don't and maybe should not optimize, unless you encounter performance issues in production). To opt-in to FastField support, all formik-antd components provide an optional fast?: boolean prop. Setting this to true enables the optimization:

<Input name='firstName' fast={true} />

Table

The table components comes with additional helper buttons to add and delete rows. An example can be seen in the codesandbox.

Lists and Nested objects

Nested objects and arrays can be accessed with lodash-like bracket syntax as described in the Formik documentation.

<Input name='friends[0].firstName' />

Advanced setup

You can checkout this github template project get the following setup (and more).

If you do not want to import the full ant design library and its stylesheet (in order to reduce the bundle size) you can import specific components and their stylesheet by their path, as it is described in the antd documentation https://ant.design/docs/react/getting-started#Import-on-Demand

import Input from 'formik-antd/es/input'
import 'formik-antd/es/input/style'

Some build tools like webpack are now able to "tree shake", meaning unused code from ant design will not be bundled.

As writing imports like this is a little cumbersome there is a babel import helper: https://github.com/ant-design/babel-plugin-import. In create-react-app projects babel plugins do not work out of the box. With third party projects like customize-cra and react-app-rewired we are able to change the webpack config. Be warned though, the team behind create-react-app does not support this scenario, so if you run into problems you are on your own.

npm install babel-plugin-import customize-cra react-app-rewired --save-dev

config-overrides.js

const path = require('path')
const { override, fixBabelImports } = require('customize-cra')

module.exports = override(
  fixBabelImports('antd', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css',
  }),
  fixBabelImports('formik-antd', {
    libraryName: 'formik-antd',
    libraryDirectory: 'es',
    style: 'css',
  }),
)

package.json

  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test"
  }

Playground & Contributions

If you want to dig into the source code and test locally you can use https://github.com/jannikbuschke/Formik-antd-playground (clone with the --recursive flag and follow the README, its pretty simple).

TypeScript

Types are included.

Typechecking limitations

Form values currently cannot be typechecked (at least to my knowledge). For example the following ideally would give a compile error:

<Formik<{name:string}> initialValues={{name:""}}>
  <Input name="naem" />
</Formik>

Typescript cannot (yet) enforce types of children. In the future this hopefully will be possible.

Related projects

License

MIT

Contributors

Special thanks to all contributors:

Nile Daley
Nile Daley

💻
James W Mann
James W Mann

💻
Jannik Buschke
Jannik Buschke

💻
Lars-Jørgen Kristiansen
Lars-Jørgen Kristiansen

💻
Adam
Adam

💻
jeessy2
jeessy2

💻
Pavan Agrawal
Pavan Agrawal

📖
Khartir
Khartir

💻
Yury Kozhenov
Yury Kozhenov

💻
Tonye Jack
Tonye Jack

💻
Edon Gashi
Edon Gashi

🚇
Roman Tsegelskyi
Roman Tsegelskyi

💻
Daniel Schulz
Daniel Schulz

💻
Harry Green
Harry Green

📖
Daniel Huth
Daniel Huth

💻
Gabriel Berlanda
Gabriel Berlanda

💻 📖
Alexandre Giard
Alexandre Giard

🤔
kissthom
kissthom

🐛
Chris Higgins
Chris Higgins

💻
Felipe Lima
Felipe Lima

💻
Frédéric Barthelet
Frédéric Barthelet

💻
Vincent
Vincent

💻

This project follows the all-contributors specification. Contributions of any kind welcome!