Skip to content

Instantly share code, notes, and snippets.

@chapagainmanoj
Last active March 19, 2020 08:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chapagainmanoj/a74fce03e3e24d063e5d728e9fbb271c to your computer and use it in GitHub Desktop.
Save chapagainmanoj/a74fce03e3e24d063e5d728e9fbb271c to your computer and use it in GitHub Desktop.
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