How to use checkbox as Radio Button in ReactJS with hooks? - javascript

I'm Building a filter in ReactJS with hooks and now I need apply some style to the checkboxes.. The CSS is not the problem, I already did it in vanilla:
function checkOne(checkbox) {
var checkboxes = document.getElementsByName('plan')
checkboxes.forEach((item) => {
item !== checkbox ? item.checked = false : item.checked = true;
})
}
=======================================================================
X 3
<label for="premium">
<input
type="checkbox"
name="plan"
onclick="checkOne(this)"
class="input-check"
value="Premium"
>
<span
class="checkmark"
id="premium"
>
Premium
</span>
</label>
Now I need to do the same think in react with hooks and I get stuck, I'm mapping a source of products and making a list of checkboxes form the product categories...
...
const [checked, setChecked] = useState(false) //hook
...
handleChange(e, checkbox){
setProduct(e.target.value);
setSearch(e.target.value);
let checkboxes = document.getElementsByName('products')
checkboxes.forEach((item) => {
item !== checkbox ? setChecked(false) : setChecked(true);
})
}
... in render method
<div className="filters" id="top">
{uniqueProduct.map(product => (
<label key={product.id}>
<input
className='filters-available-size'
type="checkbox"
value={product.category}
onChange={handleChangeProduct} // <-- ?¿?¿ what should go here?
name='product'
/>
<span className="checkmark">
{product.category}
</span>
</label>
))}
</div>

Why do you need to use checkboxes as radio buttons? I'm going to assume because of the styling--a design decision, perhaps. In which case, I would use radio buttons for the functionality and then use CSS to hide radio buttons and show checkboxes that reflect the state of the chosen option.

Related

How to change a value inside of displayed component?

I have written a simple React code which displays a list of Film. Name, image, and "ocena" value, which should be editable. But it is in fact not editable.
I know more or less know why. Because of the value={ocena} during creation of the element in list.
<input value ={ocena} type='number' />
But I have no idea how to make it acually editable and dynamicly change the ocena value as user edits it. Is there a way ? Here is my code:
const Film = ({kk , nazwa, ocena,opis, setOcena,filmy}) => {
console.log({kk})
return(<div className="film">
<img src={kk} width={'80px'} height={'80px'} />
<li className="film_item">{nazwa}</li>
<textarea>{opis}</textarea>
<input value ={ocena} type='number'/>
<button className="delete">DELETE</button>
</div>
)
}
And the lsit itself
const Filmlist = ({filmy, setOcena , ocena}) => {
const [kk , setkk] = useState(filmy.url1);
return(
<div className="filmlist_container">
<ul className="filmlist">
{console.log(filmy)}
{filmy.map((film)=> (
<Film setOcena={setOcena} nazwa ={film.nazwa} opis = {film.opis }
ocena= {film.ocena }kk= {film.url1 } filmy={filmy}/>
))};
</ul>
</div>
)
}
Is there a simple way, or should i rewrite my code for this thing to be possible?

REACT-HOOKS: How do I store a modifed parameter made by the user?

I have checkboxes and I want to save in useState hooks the modified value made by the user. By default the current state is fixed and the checkbox is filled if my_value === 1, elif 0 unfilled. But if my user decides to uncheck it, how can I store this action. (if unchecked the value is 0).
Same idea with dropdown, the default value is fixed. The user can change the Taste( Good/Medium/Bad)or the Comments ((0/4....4/4)).
For now I get only the current state.
export default function Display() {
...
//For my checkboxes
const [availability, setAvailability] = useState(item.values[0].availability)
...
const [trust, setTrust] = useState(item.values[0].trust)
//For my dropdowns
const [taste, setTaste] = useState(item.taste)
...
const [comments, setComments] = useState(rule.comments)
function Checkbox({ value }) {
const [checked, setChecked] = useState(value);
return (
<label>
<input
type="checkbox"
checked={checked}
onChange={() => setChecked(checked => !checked)}
/>
{value}
</label>
);
}
return (
<div>
<div>
Availability : <Checkbox value={!!availability} />
</div>
....
<div >
Taste : <Dropdown style={styles.select} options={TASTE} defaultValue={LIKELIHOOD.find((t) => t.label === item.taste)} />
</div>
...
</div >
);
}
This isn't so much a hooks problem as a "where do I store my state" problem. So far I don't see any place in your implementation to store the users choices. Either the MenuItemDisplay component needs to maintain that state, or it needs to receive it from a parent component. Either way, that state (containing user choices) will need to be passed down (along with update functions) into the checkbox component as the value of a 'checked' prop, and the update functions for that state should be passed as (and adapted to) the checkbox 'onToggle' (or similar) prop

Showing Results using child when clicking a button in parent component

I am Trying to build a simple trivia quiz using React and i am stuck on as to how to show the results when the user clicks "Check Answer" Button. I need to change the colors of label reflecting correct and wrong choices.
props ={
questions: arr[str]
answers: arr[arr[str]]
correct-answer: "str"
}
export default function QuestionPage(props){let [showResults,setShowResults] = React.useState(false)let Questions = []
// create 5 questions using the data from props
function getQuestions(){
for (let i =0;i<props.questions.length;i++){
Questions.push(
<Question
key= {nanoid()}
question = {props.questions[i]}
answers = {shuffle(props.answers[i])}
correct_answer = {props.correct_answers[i]}
showResults = {showResults}
/> )
}
return Questions
}
function TotalScore(){
Questions.forEach( (value,index)=>{
console.log(value,"\t",index)
})
//get all inputs using DOM and check
}
return (
<main>
{getQuestions()}
{ showResults && <TotalScore />}
<button onClick={() => setShowResults(true)}>Check Answers</button>
</main>
)
}
I was hoping to change the background color of labels inside the input field I have created for answering the questions :
Red if user selected the wrong option
Green if correct.
I can handle the css bit of coloring, just need to understand "how to implement the passing of command from button in parent component down to child component" functionality in React.
Below is the code for Question.js Component
export default function Question ({question,answers,correct_answer,showResults}) {
const [selected,setSelected] = React.useState({
selected: ""
})
function handleChange(event){
console.log(event.target,"\t",selected.selected)
setSelected( {
selected: event.target.value}
)
}
return(
<div className='question-container'>
<h4>{question}</h4>
<div className='answers-row'>
<fieldset>
<input
type="radio"
id = {answers[0]}
name = {question}
value = {answers[0]}
onChange = {handleChange}
checked = {selected.selected === answers[0]}
/>
<label htmlFor={answers[0]}>{answers[0]}</label>
<br />
<input
type="radio"
id={answers[1]}
name = {question}
value = {answers[1]}
onChange = {handleChange}
checked= {selected.selected === answers[1]}
/>
<label htmlFor={answers[1]}>{answers[1]}</label>
<br />
<input
type="radio"
id={answers[2]}
name = {question}
value = {answers[2]}
onChange = {handleChange}
checked= {selected.selected === answers[2]}
/>
<label htmlFor={answers[2]}>{answers[2]}</label>
<br />
<input
type="radio"
id={answers[3]}
name = {question}
value = {answers[3]}
onChange = {handleChange}
checked= {selected.selected === answers[3]}
/>
<label htmlFor={answers[3]}>{answers[3]}</label>
<br />
</fieldset>
</div>
</div>
)
}
In your code, you are maintaining the state ie. the answer selected by the user, on each Question component. However, when the user clicks the button QuestionPage components re-render so do its children. The getQuestions() will be invoked and components will be created again and states will again be initialized to the default value ie "".
Read this https://reactjs.org/docs/lifting-state-up.html. The example given here is similar to what you are trying to do.

Getting values from checkbox group and adding/removing them from array

I am creating a form where I have a group of checkboxes.
When click on checkbox, I would get the value of that specific checkbox and add to an Array (I am using the useState hook) and if I uncheck it will remove that element from the array.
That's my code so far:
const ContactUs = () => {
const [cities, setCities] = useState([])
useEffect(() => {
console.log(cities)
})
const handleCheck = (e) => {
if (e.target.checked) {
setCities([...cities, e.target.value])
} else {
removeCities()
}
}
const removeCities = () => {
setCities(() => cities.splice(DT.length - 1, 1))
}
return (
<Content>
<form>
<SectionTitle>Day Tours</SectionTitle>
<Checkbox
type="checkbox"
id="1"
label="Dublin"
value="dublin"
name="dublin"
onChange={handleCheck}
/>
<Checkbox
type="checkbox"
id="2"
label="New York"
value="New York"
name="new-york"
onChange={handleCheck}
/>
<Checkbox
type="checkbox"
id="3"
label="Torino"
value="Torino"
name="torino"
onChange={handleCheck}
/>
</form>
</Content>
)
}
I can add it to the array but I can't seem to remove it (or remove the right one).
I tried splice and slice methods but as I don't fully grasp their concept.
I don't know what is DT as you haven't shared your whole code, but I think you can approach this in another still functional, declarative way:
Filter out the array so it returns everything that is checked and filters (removes) the unchecked ones:
in your else block:
setCities(cities.filter(city => city !== e.target.value))
Filter will always return a new array with the values that match the filter criteria, in this case it would return everything except the e.target.value, which is what we want as based on your logic, the else block will execute when it's unchecked.

How can I require at least one checkbox to be selected for user to submit form?

I have a checkboxgroup component that I want to do some input validation on. At least one checkbox needs to be selected before the user can submit the form.
<legend>Choose field names</legend>
<CheckboxGroup
checkboxDepth={5}
name="fieldNames"
value={this.state.fieldNames}
onChange={this.fieldNamesChanged}
required
>
{fields &&
fields.map(field => {
return (
<li>
<Checkbox value={field.name} />
{field.name}
</li>
);
})}
With what I currently have in my codesandbox the form can be submitted without selecting any checkboxes. Can the required attribute be used to fix this issue or do I need to keep track of selected boxes outside of this component?
// include a value in your state defaults
this.state = {
...,
submitDisabled: true
};
// update the value when a checkboxe's value changes
fieldNamesChanged = newFieldNames => {
this.setState({
...,
submitDisabled: !newFieldNames.length
});
};
// use the state value to toggle the disabled property
<button
...
disabled={this.state.submitDisabled}>
Submit
</button>
Here's a demo.

Categories

Resources