-
-
Save mairh/233f6b4ffdbaaed8ec75bb0bef087e8f to your computer and use it in GitHub Desktop.
| // semantic-ui-form.js | |
| import React from 'react'; | |
| import PropTypes from 'prop-types'; | |
| import { Form, Input } from 'semantic-ui-react'; | |
| export default function semanticFormField ({ input, type, label, placeholder, meta: { touched, error, warning }, as: As = Input, ...props }) { | |
| function handleChange (e, { value }) { | |
| return input.onChange(value); | |
| } | |
| return ( | |
| <Form.Field> | |
| <As {...props} {...input} value={input.value} type={type} label={label} placeholder={placeholder} onChange={handleChange} /> | |
| {touched && ((error && <span><i>{error}</i></span>) || (warning && <span><i>{warning}</i></span>))} | |
| </Form.Field> | |
| ); | |
| } | |
| semanticFormField.propTypes = { | |
| as: PropTypes.any, | |
| input: PropTypes.object, | |
| type: PropTypes.string, | |
| label: PropTypes.string, | |
| placeholder: PropTypes.string, | |
| meta: PropTypes.object | |
| }; | |
| // validation.js | |
| export const required = value => (value ? undefined : 'Required'); | |
| export const number = value => value && isNaN(Number(value)) ? 'Must be a number' : undefined; | |
| export const email = value => { | |
| value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value) | |
| ? 'Invalid email address' | |
| : undefined; | |
| }; | |
| // your-component.js | |
| import React from 'react'; | |
| import PropTypes from 'prop-types'; | |
| import { compose } from 'redux'; | |
| import { Field, reduxForm } from 'redux-form'; | |
| import { Button, Form } from 'semantic-ui-react'; | |
| import semanticFormField from './semanticFormField'; | |
| import { required, number, minValue } from './validation'; | |
| const options = [ | |
| { key: '0', text: 'Option 1', value: '0' }, | |
| { key: '1', text: 'Option 2', value: '1' } | |
| ]; | |
| const ComponentForm = (props) => { | |
| return ( | |
| <Form name="product" onSubmit={handleSubmit(onSubmit)}> | |
| <Field name="selectExample" component={semanticFormField} as={Form.Select} options={options} label="Select label" placeholder="Select an option" validate={required} /> | |
| <Field name="textInputExample" component={semanticFormField} as={Form.Input} type="text" label="Input label" placeholder="Text Input" validate={required} /> | |
| <Field name="numberInputExample" component={semanticFormField} as={Form.Input} type="text" label="Number label" placeholder="Number Input" validate={number} /> | |
| <Field name="emailInputExample" component={semanticFormField} as={Form.Input} type="email" label="Email label" placeholder="Email Input" validate={[required, email]} /> | |
| <Button primary loading={submitting} disabled={pristine || submitting}>Submit</Button> | |
| </Form> | |
| ); | |
| }; | |
| ComponentForm.propTypes = { | |
| handleSubmit: PropTypes.func, | |
| reset: PropTypes.func, | |
| onSubmit: PropTypes.func, | |
| pristine: PropTypes.bool, | |
| submitting: PropTypes.bool | |
| }; | |
| export default compose( | |
| reduxForm({ | |
| form: 'yourComponent', | |
| enableReinitialize: true | |
| }) | |
| )(ComponentForm); | |
| // Use the above created form component anywhere else in the code base | |
| import ComponentForm from './your-component'; | |
| class ComponentWhereFormIsUsed extends React.Component { | |
| // Capturing redux form values from redux form store (pay attention to the name we defined in the previous component) | |
| onSubmit = values => {( | |
| values.selectExample, | |
| values.textInputExample, | |
| values.numberInputExample, | |
| values.emailInputExample | |
| )}; | |
| render() { | |
| return ( | |
| <ComponentForm onSubmit={this.onSubmit} /> | |
| ); | |
| } | |
| } |
@mairh I'm new to react can you add a working example, please
@mairh Thank you for your examples!
in semantic-ui-form.js, I keep getting meta error and warning undefined.. do you have any idea why?
Thanks.
Hello @mairh
Did you see that semanticFormField return <Form.Field>
and in your exemple you are using as={Form.Select} which is a sugar for <Form.Field><Select /></Form.Field>, so it renders a Form.Field inside a Form.Field ? Maybe i'm misunderstanding something.
Also, how to you make your semanticFormField works with checkboxes and radios ? I'm having a hard time trying to make it works
Thank you a lot for this gist !
Thank you! This helped me a lot.
This is very helpfull tanks for that
Great example and very helpful.....thank you for this.
Just to make it a bit funkier instead of the <span>......</span> for the errors and warnings I think <Message negative><Message.Header>etc.....</Message.Header></Message> adds that final touch.
Hey! Thanks for your example!
I am trying to have a <Field as={Form.Select} multiple selection.../> take in multiple values so that it can have default values appear on mount. The problem I am having is that I can't get value={['this', 'array', 'of_values']} to be in input of the semanticFormField (but name is)
<Field
component={semanticFormField}
name='fieldNames'
as={Form.Select}
multiple
selection
value={selectedFieldNamesInArray} //this is the problem here
options={fieldNameOptions}
label='Field'
width={8}
onChange={this.handleFieldNames}
/>
any help would be great!
Hey! Thanks for your example!
I am trying to have a
<Field as={Form.Select} multiple selection.../>take in multiple values so that it can have default values appear on mount. The problem I am having is that I can't getvalue={['this', 'array', 'of_values']}to be in input of the semanticFormField (but name is)<Field component={semanticFormField} name='fieldNames' as={Form.Select} multiple selection value={selectedFieldNamesInArray} //this is the problem here options={fieldNameOptions} label='Field' width={8} onChange={this.handleFieldNames} />any help would be great!
Update:
I figured out the problem, you should add input to the props and any onChange or onBlur methods should be included as well
<Field
component={semanticFormField}
name='fieldNames'
as={Form.Dropdown}
multiple
selection
input={ { value: selectedFieldNamesInArray, onChange: this.handleFieldNames } }
/>
However, if trying to make a certain value appear upon initial mount, it's best to use the initialValues in mapStateToProps from reduxForm
Thanks a lot! That was a big help.