I am new to react and I got a scenario where I have multiple checkboxes on my form. I want the user to check all the checkboxes only then enable the submit button on the form. On Load, the submit button will be disabled. How to do this?
Here is the code that I have written so far:
const MultipleCheckboxes = () => {
const handleChange = () => {
}
const allChecked = () => {
}
return (
<div>
<form>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value="Java"
id="languageChkDefault"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Javascript
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value="Angular"
id="languageChkDefault"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Angular
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value="Python"
id="languageChkDefault"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Python
</label>
</div> <br />
<button disabled={!allChecked}>Submit</button>
</form>
</div>
);
};
export default MultipleCheckboxes;
Can anybody help me on this? thank you
This is my solution, I hope it helps you
import { useState, useEffect } from "react";
const MultipleCheckboxes = () => {
const [allChecked, setAllChecked] = useState(false);
const [checkboxes, setCheckboxes] = useState({
javaCheckbox: false,
angularCheckbox: false,
pythonCheckbox: false
});
function handleChange(e) {
setCheckboxes({
...checkboxes,
[e.target.id]: e.target.checked
})
}
useEffect(() => {
const result = Object.values(checkboxes).every(v => v);
console.log(result);
setAllChecked(result);
}, [checkboxes]);
return (
<div>
<form>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value={checkboxes.javaCheckbox}
id="javaCheckbox"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Javascript
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value={checkboxes.angularCheckbox}
id="angularCheckbox"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Angular
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value={checkboxes.pythonCheckbox}
id="pythonCheckbox"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Python
</label>
</div> <br />
<button disabled={!allChecked}>Submit</button>
</form>
</div>
);
};
export default MultipleCheckboxes;
You can use react useState hook and set its default value to false.
const [state, setstate] = useState(false)
When the user clicks on an input box set the state to true. You may encounter some problems when the user unchecks the box, so you can use an if statement to handle state change
For example:
if (state === true){
setstate(false)
}else{
setstate(true)
}
or you can just use this code inside the handleChange function:
!state
It inverses the state to true/false accordingly.
After that you can use a ternary operator inside the component to check whether the user has checked all the boxes, if the user hasn't checked all the boxes, disable the button or else do otherwise.
For example, if the state is true (or in other words, if the user has checked the box), render the normal styled button, else render the disabled button:
{state? <button className = "styled"/>: <button disabled className="styled"/>}
Of course, I have only checked the state of one input box. Now you can simply check for multiple conditions by declaring multiple states for each box.
{state1 && state2 && state3 ? <button className = "styled"/>: <button disabled className="styled"/>}
If you are not yet familiar with ternary operators, you should go through this doc Ternary operators.
If you haven't heard of useState and react hooks yet, feel free to look the React's documentation. Welcome to the React ecosystem!
Related
I created a form using this code using useState. But the issue is i want to make a code with lesser line and i want to create it with the use of keys and ids that uses only one single input tag in the code instead of multiple input tags. the code is mentioned below:
import './App.css';
import { useState } from "react";
function App() {
const [inputFields, setInputFields] = useState([
{
name:'',
email:'',
username:'',
password:'',
confirm:'',
mobile:''
}
])
const handelFormChange = (index, event) => {
let data = [...inputFields]
data[index][event.target.name] = event.target.value;
setInputFields(data);
}
const submit = (e) => {
e.preventDefault();
console.log(inputFields)
}
return (
<div className="App">
<form className="bg-light" onSubmit={submit}>
{/* <div className="form-group"> */}
{inputFields.map((input, index) => {
return(
<div key={index} className="form-group">
<label className="font-weight-regular"> Name </label>
<input type="name" name='name' required value={input.name} onChange={event => handelFormChange(index,event)}></input>
<label className="font-weight-regular"> Email </label>
<input type="text" name='email' required value={input.email} onChange={event => handelFormChange(index,event)}></input>
<label className="font-weight-regular"> Username </label>
<input type="text" name='username' required value={input.username} onChange={event => handelFormChange(index,event)}></input>
<label className="font-weight-regular"> Password </label>
<input type="password" name='password' required value={input.password} onChange={event => handelFormChange(index,event)}></input>
<label className="font-weight-regular"> Confirm Password </label>
<input type="password" name='confirm' required value={input.confirm} onChange={event => handelFormChange(index,event)}></input>
<label className="font-weight-regular"> Mobile Number </label>
<input type="text" name='mobile' required value={input.mobile} onChange={event => handelFormChange(index,event)}></input>
</div>
)
})}
<button onClick={submit}>Submit</button>
</form>
</div>
)
}
export default App;
So i tried to mention the make a form and i am a fresher in this field so i dont know how to make a form with single input field but i have the requirement of this code
It's possible to use a single input field to create a form with multiple inputs by using the 'name' attribute on the input field. The name attribute allows you to identify which input field the data is coming from when the form is submitted.
I cant quite figure out how I am supposed to pass an object as a prop when using useState in Next JS.
I have a lorem ipsum generator that I created in javascript functions. I have a component called Paragraphs that houses it. I need to pass in two properties,
a number of paragraphs.
a sentence length.
The paragraph length is set by a text input where the user types in 1-10. The sentence length is set by radio buttons.
The problem I am running into is that when you input any value, the setState gets called (intentional) and it works, the problem is, it constantly works. I want to only have it update when I click my "Adventure" button to generate the data. I am unsure how to set those values to an set them as object property values and pass the object then.
Below is my code for the fields
import React, { useState } from 'react'
import Paragraph from '../components/ipsum/Paragraph.js'
export default function rpgIpsum() {
const [paragraphNumber, setParagraphNumber] = useState(5)
const [sentenceLength, setSentenceLength] = useState(5)
const [data, setData ] = useState({
outputProps: {
paragraphNumber: 5,
sentenceLength: 5
}
})
return (
<div>
{data.outputProps.paragraphNumber}
<div className="container">
<div className="row">
<div className="col-md-2 d-sm-none d-xs-none d-md-block d-none">
{/* <img src="public/images/Bard.jpg" alt="Lorem Ipsum Bard!" className="img-fluid" /> */}
</div>
<div className="col-md-10">
<h2>Looking to add some fun to your filler text?</h2>
<h5>Let's Spiffy up your copy with some RPG inspired Lorem Ipsum!</h5>
<div className="form-container">
<p>First, select how many paragraphs you want.
<input
type="text"
name="para"
value={paragraphNumber}
className="para-box"
required
onInput={
event => setParagraphNumber(parseInt(event.target.value))
}
/>
<small id="para-box-help" className="form-text text-muted">(Max of 10)</small>
</p>
<p>Next, select the length of the sentences</p>
<div className="form-check form-check-inline">
<input
className="form-check-input"
type="radio"
name="sentences"
value="3"
required
onInput={
event => setSentenceLength(parseInt(event.target.value))
}
/>
<label className="form-check-label" htmlFor="inlineRadio1">Short</label>
</div>
<div className="form-check form-check-inline">
<input
className="form-check-input"
type="radio"
name="sentences"
value="5"
required
onInput={
event => setSentenceLength(parseInt(event.target.value))
}
/>
<label className="form-check-label" htmlFor="inlineRadio2">Medium</label>
</div>
<div className="form-check form-check-inline">
<input
className="form-check-input"
type="radio"
name="sentences"
value="7"
required
onInput={
event => setSentenceLength(parseInt(event.target.value))
}
/>
<label className="form-check-label" htmlFor="inlineRadio3">Long</label>
</div>
<div className="form-group">
<button type="submit" className="btn btn-primary"
onClick={ event => "what do i do here?" ))}
>Adventure!</button>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-12">
<hr />
<Paragraph paragraphNumber={data.outputProps.paragraphNumber} sentenceLength={data.outputProps.sentenceLength}/>
</div>
</div>
</div>
</div>
)
}
What I'd do is refactor the input functionality into a separate component and use a function prop to pass the input data to an outer component that also contains the Paragraph component, like so:
// rpgIpsum.js
export default function rpgIpsum() {
const [settings, setSettings] = useState({
paragraphNumber: 5,
sentenceLength: 5
});
return (
<>
<ParagraphInput onSubmit={setSettings} />
<Paragraph {...settings} />
</>
);
}
// ParagraphInput.js
export default function ParagraphInput({ onSubmit }) {
const [paragraphNumber, setParagraphNumber] = useState(5);
const [sentenceLength, setSentenceLength] = useState(5);
return (
<div>
{/* ... */}
<button
type="submit"
onClick={() => onSubmit({paragraphNumber, sentenceLength})}
>Adventure!</button>
</div>
);
}
That way, settings in rpgIpsum is only updated when the button inside ParagraphInput is pressed, and not on every change of the inputs.
You need to make a parent component and lift the state of your components up to that parent component. Or you can use Redux for your state management, it would make it easier for you to pass data to your components.
I want to select only one option in the group of radio buttons. i can only find class component code online.
Also help me with a onChange function to handle this.
const [radioOption, setradioOption]= useState(true)
const handleRadioChange = () =>{
}
return(
<>
<Form.Group
inline
style={{
display:'flex',
justifyContent:'space-between'}}
>
<Form.Radio
onChange={handleRadioChange}
value="All devices"
label='All devices'
defaultChecked/>
<Form.Radio
onChange={handleRadioChange}
value='Mobile only'
label='Mobile only'/>
<Form.Radio
onChange={handleRadioChange}
value='Desktop only'
label='Desktop only'/>
</Form.Group>
</>)
To select only one option in the group of radio buttons you need to use same name in every input of radio. To save your choice we can use useState. Here is the complete example:
import React, { useState } from "react";
function Demo() {
const [gender, setGender] = useState("Male");
function onChangeValue(event) {
setGender(event.target.value);
console.log(event.target.value);
}
return (
<div onChange={onChangeValue}>
<input type="radio" value="Male" name="gender" checked={gender === "Male"} /> Male
<input type="radio" value="Female" name="gender" checked={gender === "Female"}/> Female
<input type="radio" value="Other" name="gender" checked={gender === "Other"} /> Other
</div>
);
}
export default Demo;
I am trying to get useFormik to validate radio groups, but it seems not to work, here is a brief example of what I am doing, whenever I submit the form after checking any of the radio input, formik throws validation error, ({currState:"you must choose property state"}), even though I choose an option.
I realized getFieldProps attaches value field to the radio, so i tried using defaultValue then react throws an error about choosing one of controlled and uncontrolled components.
import { useFormik } from "formik"
export function ListProperty(){
const { handleSubmit, getFieldProps, touched, errors } = useFormik(
{
initialValues: {
currState:"",
},
validationSchema:Yup.object().shape({
currState:Yup.string().required("you must choose property state")
}),
return (
<form onSubmit={handleSubmit} >
<div className="form-group inline">
<div className="form-control">
<input type="radio"
name="currState"
{...getFieldProps("currState")}
value="serviced"
/>
<label>serviced</label>
</div>
<div className="form-control">
<input
type="radio"
value="furnished"
name="currState"
{...getFieldProps("currState")}
/>
<label>furnished</label>
</div>
<div className="form-control">
<input
type="radio"
value="newlybuilt"
name="currState"
{...getFieldProps("currState")}
/>
<label>newly built</label>
</div>
</div>
<button type="submit">submit </button>
</form>
)
}
I gave up on the implementation with getFieldProps and did it simpler, like this:
import { useFormik } from 'formik'
export default function Component() {
const formik = useFormik({
initialValues: {
radioButtonValue: ''
},
onSubmit: values => console.log(values)
})
const handleRadioButtons = e => formik.values.radioButtonValue = e.target.value
return (
<form onSubmit={formik.handleSubmit}>
<input
type="radio"
id="one"
name="group"
value="One"
onChange={e => handleRadioButtons(e)}
required
/>
<label htmlFor="one">One</label>
<br />
<input
type="radio"
id="two"
name="group"
value="Two"
onChange={e => handleRadioButtons(e)}
/>
<label htmlFor="two">Two</label>
<button type="submit">Submit</button>
</form>
)
}
Beware, if you use formik.values.radioButtonValue value as a useEffect dependency, then setting it like this: formik.values.radioButtonValue = e.target.value not gonna trigger the change, and useEffect won't launch (at least in my case it didn't). As an alternative, you gonna have to implement some kind of condition check with this value in your useEffect code
You need to map onChange like below.
<input
type="radio"
value="furnished"
name="currState"
onChange={getFieldProps("currState").onChange}
/>
I am working on a custom radiobutton/checkbox component -- based off the renderField. The component appears to render fine, but when I've added a "checked" parameter to this it breaks. The field is selected correctly - but when toggling options it looks like it tries to force check the old item.
//renderField
import React from 'react'
const renderField = ({input, label, type, meta: {touched, error, warning}}) => (
<div className='field'>
<label>
{touched &&
<span>
{label}
</span>
}
{touched &&
((
error &&
<span className="error">
: {error}
</span>) ||
(
warning &&
<span className="warning">
: {warning}
</span>
))}
</label>
<div>
<input {...input} placeholder={label} type={type} />
</div>
</div>
)
export default renderField
here is the new field -- the markup is different to the standard input fields.
//renderRadioCheckField
import React from 'react'
import _ from 'underscore';
function renderRadioCheckField({input, label, type, checked, meta: {touched, error, warning}}) {
const randId = _.uniqueId('radiocheck_');
return (
<div className='field'>
<div>
<input {...input} placeholder={label} type={type} id={randId} checked={checked} />
<label className="group-label" htmlFor={randId}>
{label}
</label>
</div>
</div>
);
}
export default renderRadioCheckField
--
on my form component I am importing these in and calling them as such
<Field name="test" type="text" component={renderField} label="test" />
<br/><br/>
<Field name="radio-group1" type="radio" component={renderRadioCheckField} value="check1" label="Apple2" />
<Field name="radio-group1" type="radio" component={renderRadioCheckField} value="check2" label="Peach2" checked="true" />
<Field name="radio-group1" type="radio" component={renderRadioCheckField} value="check3" label="Orange2" />
<br/><br/>
<Field name="check-group1" type="checkbox" component={renderRadioCheckField} value="check1" label="Yes" />
<Field name="check-group1" type="checkbox" component={renderRadioCheckField} value="check2" label="No" checked="true" />
Don't use the checked="true". Instead do following in your componentDidMount() method of React Redux Form component.
componentDidMount(){
const {radio-group1} = this.props;
//Sets initial default checked value
this.props.change('radio-group1','check2');
}
You can do same for checkboxes.