withKingpin
Basics
Modern forms require more than just <input />
and <textarea />
components.
Kingpin plan is to add pluggable external components like Typeaheads
, Slider
, Dropdown
ecc.
specifically desinged and developed to work within a Kingpin Form
out of the box.
In order to make Kingpin extensible by anyone it's possible create custom
components with the withKingpin
HOC.
Following an example to learn how to use the withKingpin
HOC.
Props
The created element will have the following props.
Name | Mandatory | Purpose |
---|---|---|
name | true | A string which describe the element. Will be the element key in the submit payload |
initialValue | false | The element initial value |
validation | false | A single (or an array/object of) function(s) to validate the element. Check the doc |
errorClassName | false | A className that is attached to the className on error. Check validation for more. |
Custom attributes | false | All your custom attributes |
Example: Kingpin and react-select
Let's say that for our form we need an "enhanced" select component (compared to the plain HTML <select />
)
and for this reason we decide to use react-select (you can use
whatever third part component or even build your own).
After having installed react-select
with your favourite package manager let's create the new custom component.
- Typescript
- Javascript
// File: ./Select.tsx
import { withKingpin } from 'kingpin-react-form'
import { useState } from 'react'
import Select, { SingleValue } from 'react-select'
type Option = { value: string; label: string }
const options: Option[] = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
]
type CustomSelectProps = {
updateState: (val: SingleValue<Option>) => void
initialValue?: SingleValue<Option>
}
function CustomSelect({ updateState, initialValue }: CustomSelectProps): JSX.Element {
const [selectedOption, setSelectedOption] = useState<SingleValue<Option>>(initialValue)
return (
<div className="App">
<Select
defaultValue={selectedOption}
onChange={(val) => {
setSelectedOption(val)
updateState(val)
}}
options={options}
/>
</div>
)
}
export default withKingpin<CustomSelectProps, SingleValue<Option>>(CustomSelect)
// File: ./Select.tsx
import { withKingpin } from 'kingpin-react-form'
import { useState } from 'react'
import Select from 'react-select'
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
]
function CustomSelect({ updateState, initialValue }) {
const [selectedOption, setSelectedOption] = useState(initialValue)
return (
<div className="App">
<Select
defaultValue={selectedOption}
onChange={(val) => {
setSelectedOption(val)
updateState(val)
}}
options={options}
/>
</div>
)
}
export default withKingpin(CustomSelect)
Now we are ready to use our new component within our Form
component.
- Typescript
- Javascript
// File: ./App.tsx
import CustomSelect './Select'
import type { FormEvent } from 'react'
import { Form, FormResult } from 'kingpin-react-form'
function App(): JSX.Element {
const submit = (e: FormEvent<HTMLFormElement>, data: FormResult) => {
e.preventDefault()
console.log(data)
// data: {
// isValid: true,
// payload: {
// hoc-select: null
// }
// }
}
return (
<Form onSubmit={submit}>
<CustomSelect name="hoc-select" />
<button type="submit">Submit</button>
</Form>
)
}
// File: ./App.tsx
import CustomSelect './Select'
import { Form } from 'kingpin-react-form'
function App() {
const submit = (e, data) => {
e.preventDefault()
console.log(data)
// data: {
// isValid: true,
// payload: {
// hoc-select: null
// }
// }
}
return (
<Form onSubmit={submit}>
<CustomSelect name="hoc-select" />
<button type="submit">Submit</button>
</Form>
)
}