Required rule for group of checkboxed - reactjs

Shared answer https://stackoverflow.com/a/71804470/20847211
**How can i use required rule for group of checkboxes in this code **
import React, { useState } from 'react'
import { useForm } from 'react-hook-form'
export default function App() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
defaultValues: { months: ['January'] },
})
const onSubmit = (data: any) => console.log(data)
console.log(errors)
return (
<div className='mx-auto justify-center p-32 flex'>
<form onSubmit={handleSubmit(onSubmit)}>
<div className='p-2'>
<label htmlFor=''>January</label>
<input
type='checkbox'
value='January'
placeholder='January'
{...register('months')}
className='mx-3'
/>
</div>
<div className='p-2'>
<label htmlFor=''>February</label>
<input
type='checkbox'
value='February'
placeholder='February'
{...register('months')}
className='mx-3'
/>
</div>
I tried to place required to fields, but it'nt working

Related

How to connect react-hook-form ref with a custom input component

I'm interested in using react-hook-form for data validation. I have a custom TextField component as follows.
src/components/Fields.js
function Label({ id, children }) {
return (
<label
htmlFor={id}
className="block mb-3 text-sm font-medium text-gray-700"
>
{children}
</label>
);
}
export function TextField({
id,
label,
inputRef,
type = "text",
className = "",
...props
}) {
return (
<div className={className}>
{label && <Label id={id}>{label}</Label>}
<input id={id} ref={inputRef} type={type} {...props} />
</div>
);
}
I've tried using react-hook-form like this..
src/App.js
import { TextField } from "./components/Fields";
import { useForm } from "react-hook-form";
import { useEffect } from "react";
export default function App() {
const {
register,
handleSubmit,
watch,
formState: { errors },
} = useForm();
const mytest = register("mytest", { required: "mytest is a required field" });
const onSubmit = (data) => console.log(data);
useEffect(() => console.log(errors), [errors])
return (
<form onSubmit={handleSubmit(onSubmit)}>
<TextField
id="mytest"
name={mytest.name}
inputRef={mytest.ref}
label="This is a test"
placeholder="Placeholder"
/>
<input type="submit" />
</form>
);
}
but it's not working properly.
I've also tried using forwardRef to no avail.
Finally got this working after applying forwardRef properly. Still curious if there's a better way, so I'll leave this question open.
src/components/Fields.js
import { forwardRef } from "react";
function Label({ id, children }) {
return (
<label
htmlFor={id}
className="block mb-3 text-sm font-medium text-gray-700"
>
{children}
</label>
);
}
export const TextField = forwardRef(function TextField({
id,
label,
type = "text",
className = "",
...props
}, ref) {
return (
<div className={className}>
{label && <Label id={id}>{label}</Label>}
<input id={id} ref={ref} type={type} {...props} />
</div>
);
});
src/App.js
import { TextField } from "./components/Fields";
import { useForm } from "react-hook-form";
import { useEffect } from "react";
export default function App() {
const {
register,
handleSubmit,
watch,
formState: { errors },
} = useForm();
const mytest = register("mytest", { required: "mytest is a required field" });
const onSubmit = (data) => console.log("data", data);
useEffect(() => console.log(errors), [errors])
return (
<form onSubmit={handleSubmit(onSubmit)}>
<TextField
id="mytest"
label="This is a test"
placeholder="Placeholder"
{...mytest}
/>
{errors.mytest && <>{errors.mytest.message}</>}
<input type="submit" />
</form>
);
}

Why is my error message not showing up when I click enter?

I'm trying to have an error message pop up if the user submits an email without inputting a recipient, however, nothing happens upon clicking enter. Is there something I'm missing? pls help
import React from "react";
import "./SendMail.css";
import CloseIcon from "#mui/icons-material/Close";
import { Button } from "#mui/material";
import { useForm } from "react-hook-form";
const SendMail = () => {
const {
register,
handleSubmit,
watch,
formState: { errors },
} = useForm();
const onSubmit = (formData) => {
console.log(formData);
};
return (
<div className="sendmail">
<div className="sendmail__header">
<h3>New Message</h3>
<CloseIcon className="sendmail__close" />
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<input
name="to"
type="text"
placeholder="To"
{...register("to", { required: true })}
/>
{errors.to && <p className="sendMail__error">To is Required</p>}
<div className="sendmail__options">
<Button>Send</Button>
</div>
</form>
</div>
);
};
export default SendMail;
Add the submit type in your button
<div className="sendmail__options">
<Button type="submit">Send</Button>
</div>

How to validate if first array doesn't have value from second array by radio buttons with YUP

I select first radio button to render first array of radio buttons with colors, select one of the colors, then I select second radio to render second array of radio buttons with colors. If my selected color from first array doesn't include of second array, how to show error?
CodeSandbox: https://codesandbox.io/s/focused-microservice-l4q3re?file=/src/App.tsx
import React, { useState } from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "#hookform/resolvers/yup";
import * as yup from "yup";
export default function App() {
const schema = yup.object().shape({
choose: yup.string().typeError("select first or second").required(),
color: yup
.string()
.typeError("selected color doesn't include of this array")
.required("select color")
});
const {
register,
formState: { errors },
handleSubmit
} = useForm({
resolver: yupResolver(schema)
});
const onSubmit = (data: any) => {
console.log(data);
};
const onError = (error: any) => {
console.log(error);
};
let colors = [
["black", "white", "pink"],
["black", "red", "blue"]
];
const [select, setSelect] = useState<number>();
return (
<form onSubmit={handleSubmit(onSubmit, onError)}>
<label>
<input
type="radio"
onClick={() => setSelect(0)}
value={"first"}
{...register("choose")}
/>
first
</label>
<label>
<input
type="radio"
onClick={() => setSelect(1)}
value={"second"}
{...register("choose")}
/>
second
</label>
<p> {errors && errors.choose?.message}</p>
<div>
{select != null &&
colors[select].map((color: any, i: number) => (
<label key={i}>
<input
type="radio"
value={color}
{...register("color")}
/>
{color}
</label>
))}
{select != null && <p> {errors && errors.color?.message}</p>}
</div>
<button type="submit">Add</button>
</form>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
The final code for App.tsx
Paste this in App.tsx in your given sandbox to see the result.
import React, { useState } from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "#hookform/resolvers/yup";
import * as yup from "yup";
export default function App() {
const schema = yup.object().shape({
choose: yup.string().typeError("select first or second").required(),
color: yup
.string()
.typeError("selected color doesn't include of this array")
.required("select color")
});
const {
register,
formState: { errors },
handleSubmit
} = useForm({
resolver: yupResolver(schema)
});
const onSubmit = (data: any) => {
console.log(data);
};
const onError = (error: any) => {
console.log(error);
};
let colors = [
["black", "white", "pink"],
["black", "red", "blue"]
];
const [select, setSelect] = useState<number>();
const [validationState, setValidationState] = useState<boolean>();
const onClickChildRadio = (value: string) => {
const secondArray:string[] = colors[1];
const isExistInSecondArray = secondArray.includes(value);
setValidationState(isExistInSecondArray);
};
return (
<form onSubmit={handleSubmit(onSubmit, onError)}>
<label>
<input
type="radio"
onClick={() => setSelect(0)}
value={"first"}
{...register("choose")}
/>
first
</label>
<label>
<input
type="radio"
onClick={() => setSelect(1)}
value={"second"}
{...register("choose")}
/>
second
</label>
<p> {errors && errors.choose?.message}</p>
<div>
{select != null &&
colors[select].map((color: any, i: number) => (
<label key={i}>
<input
onClick={(e) => onClickChildRadio(e.target.value)}
type="radio"
value={color}
{...register("color")}
/>
{color}
</label>
))}
{select != null && <p> {errors && errors.color?.message}</p>}
</div>
<button type="submit">Add</button>
<p>
Validate :
{validationState
? "Value exist in second array"
: "Value doesn't exist in second array"}
</p>
</form>
);
}

React Hook Form with file just submitting fakepath

I'm trying to add an <Input type="file" to my react-hook-form, but it submit a C:\fakepath when I submit the form.
import React from "react";
import { Controller, useForm } from "react-hook-form";
import { Button, Form, Label, Input } from "reactstrap";
const App = () => {
const {
handleSubmit,
control,
setValue,
formState: { errors }
} = useForm();
const submitData = (data) => {
console.log(data);
};
return (
<div className="row">
<div className="col-sm-12 col-md-12 col-xl-12">
<Form onSubmit={handleSubmit(submitData)}>
<div className="row">
<div className="col-sm-6">
<Label for="file">File</Label>
<Controller
name="file"
control={control}
render={({ field }) => (
<Input {...field} type="file" id="file" />
)}
/>
</div>
</div>
<Button type="submit" color="primary">
Submit
</Button>
</Form>
</div>
</div>
);
};
export default App;
Here is the sandbox: https://codesandbox.io/s/morning-water-hyi9o
How can I use files with react-hook-form?
Thanks
You can find a solution here: https://github.com/react-hook-form/react-hook-form/discussions/5394#discussioncomment-848215
Here is another way to achieve that with register:
import React from "react";
import { useForm } from "react-hook-form";
import { Button, Form, Label, Input } from "reactstrap";
const App = () => {
const { register, handleSubmit } = useForm();
const submitData = (data) => {
console.log(data);
};
const { ref, ...field } = register("file");
return (
<div className="row">
<div className="col-sm-12 col-md-12 col-xl-12">
<Form onSubmit={handleSubmit(submitData)}>
<div className="row">
<div className="col-sm-6">
<Label for="file">File</Label>
<Input {...field} innerRef={ref} type="file" id="file" />
</div>
</div>
<Button type="submit" color="primary">
Submit
</Button>
</Form>
</div>
</div>
);
};
export default App;
I had the same problem and I solved it by changing the object data.file = e.target.file.files in the onSubmit as follows:
import React from "react";
import { Controller, useForm } from "react-hook-form";
import { Button, Form, Label, Input } from "reactstrap";
const App = () => {
const {
handleSubmit,
control,
setValue,
formState: { errors }
} = useForm();
const submitData = (data, e) => {
data.file = e.target.file.files
console.log(data);
};
return (
<div className="row">
<div className="col-sm-12 col-md-12 col-xl-12">
<Form onSubmit={handleSubmit(submitData)}>
<div className="row">
<div className="col-sm-6">
<Label for="file">File</Label>
<Controller
name="file"
control={control}
render={({ field }) => (
<Input {...field} type="file" id="file" />
)}
/>
</div>
</div>
<Button type="submit" color="primary">
Submit
</Button>
</Form>
</div>
</div>
);
};
export default App;

How to display array data in form field in Ionic ReactJS?

I have some data fetched from Laravel API and stored in an array. I would like to display the value of the data in the form field so that users can edit the value. The array is as follows:
Array Data
I can display the other field data e.g si_t_street1 that is not being stored in an array simply by using the variable name as the property value of 'name' of the field.
Data Not Stored In Array
Below is the snippet of my code:
import React, { useContext, useEffect, useState } from 'react';
import { useForm } from "react-hook-form";
import { yupResolver } from '#hookform/resolvers/yup';
import * as Yup from 'yup';
import * as api from '../../services/api';
import { IonHeader, IonToolbar, IonButtons, IonBackButton, IonTitle, IonContent, IonButton, IonAlert, IonLoading, IonModal } from '#ionic/react';
import { NavContext } from "#ionic/react";
const AbroadApp: React.FC = (props: any) => {
const { id } = props.match.params.id ?? ``;
const isAddMode = (props.match.params.id) ? false : true;
const { register, handleSubmit, reset, setValue, errors, formState } = useForm({
resolver: yupResolver(validationSchema)
});
function onSubmit(data: any) {
return isAddMode
? createRegAbroad(data)
: updateRegAbroad(id, data);
}
useEffect(() => {
if (!isAddMode) {
api.getRegAbroadById(props.match.params.id).then(regAbroad => {
let fields = [
'si_t_street1',
'si_t_street2',
'si_t_street3',
'street1'
];
let regAbroadArr: any = [];
regAbroadArr.push(regAbroad.data.data);
fields.map(field => {
setValue(field, regAbroadArr[0][field])
})
setLoading(false)
});
}
}, []);
return (
<>
<IonContent>
<form onSubmit={handleSubmit(onSubmit)} onReset={reset}>
<input name="id" ref={register} type="hidden" autoComplete="off" />
<div className="row">
<div className="col-12">
<label>
Street 1{" "}
<span className="text-danger">*</span>
</label>
<div className="form-group">
<input name="si_t_street1" ref={register} className={`form-control ${errors.si_t_street1 ? 'is-invalid' : ''}`} type="text" autoComplete="off" />
<div className="invalid-feedback">
{errors.si_t_street1?.message}
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<label>
Street 1{" "}
<span className="text-danger">*</span>
</label>
<div className="form-group">
<input name="street1" ref={register} className={`form-control ${errors.street1 ? 'is-invalid' : ''}`} type="text"
autoComplete="off" value={country[0].street1} />
<div className="invalid-feedback">
{errors.street1?.message}
</div>
</div>
</div>
</div>
</form>
</IonContent>
</>
);
}
export default AbroadApp;
I tried getting the value of street1 property of the country array but the above code throws an error: cannot find name 'Country'. What is the right way to get the value to display?
It's unclear where you've defined your "country" variable.

Resources