Last active
March 19, 2020 08:53
-
-
Save chapagainmanoj/a74fce03e3e24d063e5d728e9fbb271c to your computer and use it in GitHub Desktop.
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 React, {useEffect} from "react"; | |
import { useForm, useFormContext, FormContext } from "react-hook-form"; | |
import * as yup from 'yup'; | |
import styles from './FormComponent.css' | |
export function Form({ | |
validation, | |
defaults, | |
onSubmit, | |
actions, | |
formClass, | |
fields, | |
children, | |
resolver, | |
...other | |
}) { | |
const methods = useForm({ | |
mode: 'onBlur', | |
validationSchema: validation, | |
validationResolver: resolver | |
}); | |
const {handleSubmit} = methods; | |
return ( | |
<React.Fragment> | |
<FormContext {...methods}> | |
<form onSubmit={handleSubmit(onSubmit)} className={['ui form', formClass].filter(Boolean).join(' ')}> | |
{fields && fields.map( field => ( | |
<Field key={field.name} {...field} /> | |
))} | |
{children} | |
{actions && actions.map( action => ( | |
<Action key={action.type || action} {...action} /> | |
))} | |
</form> | |
</FormContext> | |
</React.Fragment> | |
); | |
} | |
const Field = (props) => { | |
switch (props.type) { | |
case 'select': | |
return <Select {...props} /> | |
case 'text': | |
return <Input {...props} /> | |
case 'radio': | |
return <Radio {...props} /> | |
case 'checkbox': | |
return <Checkbox {...props} /> | |
default: | |
return <div className='ui error message'><p>Invalid field.</p></div> | |
} | |
} | |
const Action = (props) => { | |
const {type, buttonClass, label, onClick} = props; | |
const {handleSubmit} = useFormContext(); | |
switch (type) { | |
case 'submit': | |
return ( | |
<button | |
className={['ui button primary', buttonClass].filter(Boolean).join(' ')} {...props}> | |
{label || 'Submit'} | |
</button> | |
) | |
case 'reset': | |
return ( | |
<div | |
className={['ui button', buttonClass].filter(Boolean).join(' ')} {...props}> | |
{label || 'Reset'} | |
</div> | |
) | |
default: | |
return (<div | |
className={['ui button', buttonClass].filter(Boolean).join(' ')} {...props} onClick={handleSubmit(onClick)}> | |
{label || 'Reset'} | |
</div>) | |
} | |
} | |
export function Input({ label, placeholder, name, ...rest }) { | |
const {register, errors} = useFormContext() | |
return ( | |
<div className='field'> | |
{label && <label htmlFor={name}>{label}</label>} | |
<input name={name} placeholder={placeholder} ref={register} {...rest} /> | |
{errors[name] && <p className={styles.error}>{errors[name].message}</p>} | |
</div> | |
) | |
} | |
export function Checkbox({ label, type, uiClass, name, ...rest }) { | |
const {register, errors} = useFormContext() | |
return ( | |
<div className='field'> | |
<div className={`ui ${type || ''} checkbox ${uiClass}`}> | |
<input name={name} type='checkbox' ref={register} {...rest} /> | |
{label && <label>{label}</label>} | |
{errors[name] && <p className={styles.error}>{errors[name].message}</p>} | |
</div> | |
</div> | |
) | |
} | |
export function Radio({ label, name, ...rest }) { | |
const {register, errors} = useFormContext() | |
return ( | |
<div className='field'> | |
<div className='ui radio checkbox'> | |
<input name={name} type='radio' ref={register} {...rest} /> | |
{label && <label>{label}</label>} | |
</div> | |
{errors[name] && <p className={styles.error}>{errors[name].message}</p>} | |
</div> | |
) | |
} | |
export function Select({ | |
label, uiClass, | |
placeholder, options, name, ...rest }) { | |
const {register, unregister, errors, setValue, triggerValidation, clearError} = useFormContext(); | |
const handleOnChange = (value, text) => { | |
if (value) { | |
setValue(name, options[value].value, true); | |
clearError(name) | |
} else { | |
setValue(name, undefined); | |
} | |
console.log(value, name); | |
} | |
useEffect(() => { | |
register({name: name}); | |
$('.ui.dropdown').dropdown({ | |
clearable: true, | |
onChange: handleOnChange | |
}); | |
return () => unregister(name) | |
}, []); | |
return ( | |
<div className='field'> | |
{label && <label htmlFor={name}>{label}</label>} | |
<div className={`ui fluid search ${uiClass || ''} selection dropdown`} {...rest} name={name} ref={register}> | |
<input type='hidden' /> | |
<i className="icon dropdown icon"></i> | |
{placeholder && <div className="default text">{placeholder}</div>} | |
<div className='menu'> | |
{options.map((item, index) => ( | |
<div key={item.key || index } className='item' data-value={index} data-text={item.text}> | |
{item.image && <img className='ui mini avatar image' src={item.image} />} | |
{item.icon && <i className={`icon ${item.icon}`} />} | |
{item.text} | |
</div> | |
))} | |
</div> | |
</div> | |
{errors[name] && <p className={styles.error}>{errors[name].message}</p>} | |
</div> | |
); | |
} | |
const HookForm = (props) => { | |
const FilterSchema = yup.object().shape({ | |
search_type: yup.string(), | |
search_value: yup.string(), | |
ordering: yup.string(), | |
owner: yup.string(), | |
tags: yup.string(), | |
state: yup.string(), | |
district: yup.string(), | |
vdc: yup.string(), | |
has_kyc: yup.string(), | |
page: yup.number(), | |
page_size: yup.number(), | |
test: yup.string().required('This field is required.'), | |
has_kyc: yup.boolean().required(), | |
email: yup.string().email().required(), | |
}); | |
const defaults = { | |
page: 1, | |
page_size: 2, | |
search_type: 'mobile', | |
} | |
const onSubmit = (data, e) => { | |
if (e) e.preventDefault(); | |
console.log(data, 'onSubmit called'); | |
} | |
const handleOnClick = (data) => { | |
console.log('hello', data); | |
} | |
const aform = useForm({ | |
mode: 'onBlur', | |
validationSchema: FilterSchema, | |
defaultValues: defaults | |
}); | |
return (<React.Fragment> | |
<div className='ui padded segment' > | |
<Form | |
validation={FilterSchema} | |
// fields={[{name: <name>, type: <type>, ...fieldProps}]} | |
defaults={defaults} | |
// formClass={''} | |
onSubmit={onSubmit} | |
actions={[{type: 'submit'}, {label: 'Say hello', onClick: handleOnClick}]} | |
> | |
<Select | |
placeholder='Select type' | |
name="test" | |
label="Sex" | |
options={[ | |
{value: 'female', text: 'Female', icon: 'star'}, | |
{value: 'male', text: 'Male', icon: 'money'}, | |
]} /> | |
<Checkbox | |
label="Has kyc" | |
name="has_kyc" | |
/> | |
<div className='equal width fields'> | |
<Input label="Search" placeholder="Enter value" name="search_value" /> | |
<Input label="Email" placeholder="Enter email" name="email" /> | |
</div> | |
</Form> | |
</div> | |
<div className='ui padded segment' > | |
<div className='ui form'> | |
<FormContext {...aform}> | |
<Select | |
placeholder='Select type' | |
name="test" | |
label="Sex" | |
options={[ | |
{value: 'female', text: 'Female', icon: 'star'}, | |
{value: 'male', text: 'Male', icon: 'money'}, | |
]} /> | |
<Checkbox | |
label="Has kyc" | |
name="has_kyc" | |
/> | |
<div className='equal width fields'> | |
<Input label="Search" placeholder="Enter value" name="search_value" /> | |
<Input label="Email" placeholder="Enter email" name="email" /> | |
</div> | |
</FormContext> | |
<div onClick={aform.handleSubmit(onSubmit)} className='ui button primary'>Submit</div> | |
<div onClick={aform.handleSubmit(handleOnClick)} className='ui button'>Say hello</div> | |
</div> | |
</div> | |
</React.Fragment>) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment