Created
August 20, 2018 22:29
-
-
Save benjaminparnell/41a237d8cd0257107fd5a748d93b324d to your computer and use it in GitHub Desktop.
formik-addresses-test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from "react"; | |
import { render } from "react-dom"; | |
import { | |
Formik, | |
FieldArray, | |
Field, | |
Form, | |
FormikProps, | |
ArrayHelpers | |
} from "formik"; | |
type Address = { | |
lineOne: string; | |
lineTwo: string; | |
city: string; | |
postcode: string; | |
}; | |
// AddressForm has all logic for finding addresses etc. The validation schema for addresses | |
// can be defined in this file too. This component relies on being rendered inside | |
// a Formik component. | |
type AddressFormState = { | |
loading: boolean; | |
postcode: string; | |
}; | |
class AddressForm extends React.Component< | |
{ | |
setValues: (address: Address) => void; | |
path: string; | |
}, | |
AddressFormState | |
> { | |
state: AddressFormState = { | |
loading: false, | |
postcode: "" | |
}; | |
onPostcodeSearchChange(e: React.FormEvent<HTMLInputElement>) { | |
this.setState({ | |
postcode: e.currentTarget.value | |
}); | |
} | |
onSearchClicked() { | |
this.setState({ loading: true }); | |
setTimeout(() => { | |
// This fills in the address at the given index with these details | |
this.props.setValues({ | |
lineOne: "3 Villiers Road", | |
lineTwo: "West Bridgford", | |
city: "Nottingham", | |
postcode: "NG2 6FR" | |
}); | |
this.setState({ loading: false }); | |
}, 2000); | |
} | |
render() { | |
const path = this.props.path; | |
return ( | |
<div> | |
<p>{path}</p> | |
<div> | |
<label>Enter your potcode</label> | |
<input | |
type="text" | |
name="postcodeSearch" | |
onChange={this.onPostcodeSearchChange.bind(this)} | |
/> | |
<button | |
type="button" | |
disabled={this.state.loading} | |
onClick={this.onSearchClicked.bind(this)} | |
> | |
Search | |
</button> | |
</div> | |
<Field name={`${path}.lineOne`} /> | |
<Field name={`${path}.lineTwo`} /> | |
<Field name={`${path}.city`} /> | |
<Field name={`${path}.postcode`} /> | |
</div> | |
); | |
} | |
} | |
// AddressesForm has all logic for listing input addresses and selecting | |
// whether to add more/edit. Could have its own state etc. Allows us to get | |
// all the noise of this complicated stuff out of the form itself. | |
const AddressesForm = ({ | |
push, | |
form | |
}: ArrayHelpers & { form: FormikProps<FormValues> }) => ( | |
<div> | |
{form.values.addresses.map((address, index) => ( | |
<AddressForm | |
key={index} | |
setValues={form.setFieldValue.bind(form, `addresses.${index}`)} | |
path={`addresses.${index}`} | |
/> | |
))} | |
<button | |
type="button" | |
onClick={() => | |
push({ | |
lineOne: "", | |
lineTwo: "", | |
city: "", | |
postcode: "" | |
}) | |
} | |
> | |
Add | |
</button> | |
</div> | |
); | |
// Root component containing the rest of the formik form | |
type FormValues = { | |
addresses: Address[]; | |
}; | |
class App extends React.Component { | |
render() { | |
return ( | |
<div> | |
<h1>Formik test</h1> | |
<Formik | |
initialValues={{ addresses: [] }} | |
onSubmit={(values: FormValues) => console.log(values)} | |
render={({ isValid }: FormikProps<FormValues>) => ( | |
<Form> | |
<FieldArray name="addresses" component={AddressesForm} /> | |
<button type="submit" disabled={!isValid}> | |
Submit | |
</button> | |
</Form> | |
)} | |
/> | |
</div> | |
); | |
} | |
} | |
render(<App />, document.getElementById("root")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment