Conditional rendering a component with using Radio button - javascript

New Tasks.js
import React, { useState } from "react";
import './NewTask.css';
import TaskDetails from "./TaskDetails";
import TaskSetting from "./TaskSetting";
const NewTask = () => {
const [checked, setChecked] = useState("inPerson");
return (
<div className="newtask-div">
<h3 className="header">New Task</h3>
<ul className="task-item">
<li style={{ fontSize: "17px" }}>Select Task Type: </li>
<li>
<input
type="radio"
checked={checked === "inPerson"}
name="inPerson" value="inPerson"
onChange={(e) => {
setChecked(e.target.value)
console.log("show task details")
}}
/>
<lable>In Person</lable>
</li>
<li>
<input
type="radio"
checked={checked === "online"}
name="online" value="online"
onChange={(e) => {
setChecked(e.target.value)
console.log("dont show task detail")
}}
/>
<lable>Online</lable>
</li>
</ul>
<TaskDetails />
</div>
)
}
export default NewTask
I am trying to use the radio button to conditional rendering the Component.
Ex: when clicking the "inPerson" it will render out the "TaskDetail" component and show others component when using "online".
Is there any method to achieve this?

You can render components conditionally based on selected value like below:
...
{
checked === "inPerson" &&
<InpersonComponents />
}
{
checked === "online" &&
<OnlineComponents />
}
...

I recommend this method with conditional rendering
{checked === "inPerson" ? <TaskDetails /> : <SomeOtherComponent />
or
{checked === "inPerson" && <TaskDetails />}
{checked === "online" && <SomeOtherComponent />}

name of inputs should be same if you want to select anyone of them
const NewTask = () => {
const [inPerson, setInPerson] = useState(true);
const [online, setOnline] = useState(false);
return (
<div className="newtask-div">
<h3 className="header">New Task</h3>
<ul className="task-item">
<li style={{ fontSize: "17px" }}>Select Task Type: </li>
<li>
<input
type="radio"
checked={online}
name="singlegroup" value="inPerson"
onChange={(e) => {
setInPerson(e.target.value)
setOnline(!e.target.value)
console.log("show task details")
}}
/>
<lable>In Person</lable>
</li>
<li>
<input
type="radio"
checked={inPerson}
name="singlegroup" value="online"
onChange={(e) => {
setOnline(e.target.value)
setInPerson(!e.target.value)
console.log("dont show task detail")
}}
/>
<lable>Online</lable>
</li>
</ul>
<TaskDetails />
{
online && <Component1/>
}
{
inPerson && <Component2/>
}
</div>
)
}
export default NewTask

Try something along the lines of
{checked !== 'inPerson' && (
<TaskDetails />
)}
Or if you want to make it modularized
const showDetails = () => {
return checked !== 'inPerson'
}
return (
...
{showDetails() && (
<TaskDetails />
)}
...
)

Related

React is it possible to receive onSubmit event in child component?

I am building a form and each of the form items (I call Cards) are inside of a child components. My submit button is in the parent component of the form items, and when I click submit, I want to to pass the event handler into the child component, may I know is there a way to do it?
I have some code snippeet here to show you guys what I have done, thanks !
// Parent Component
const card = cardsList.map(el => {
return (
<div className="card-holder" key={decodeHtml(el.question)}>
<Card
id="question1"
question={decodeHtml(el.question)}
answer={el.correct_answer}
incorrectAnswers={el.incorrect_answers}
handleSubmit={handleSubmit}
/>
</div>
)
})
function handleSubmit(event) {
event.preventDefault();
console.log(event)
}
return (
<form className="game" style={style} onSubmit={handleSubmit}>
{card}
<input type="submit" value="Submit" className="submit-btn" />
</form>
)
}
Thank you!
// Child Component
import React from "react"
import {shuffle, decodeHtml} from "/src/script/Helper.js"
function Card(props) {
const [arr, setArr] = React.useState(shuffle([0,1,2,3]));
const [checked, setChecked] = React.useState(false)
function toggleCheck(event) {
setChecked(prevChecked => {
return event.target.id
})
}
return (
<div className="card">
<h4 className="card--question">{props.question}</h4>
<div className="card--answers">
<div className="card--answer">
<input
type="radio"
name={props.question}
id={`${props.question} ans1`}
onChange={toggleCheck}
checked={checked === `${props.question} ans1`}
correct={arr[0] === 3 ? "true" : "false"}
/>
<label htmlFor={`${props.question} ans1` }>{arr[0] === 3 ? decodeHtml(props.answer) : decodeHtml(props.incorrectAnswers[arr[0]])}</label>
</div>
<div className="card--answer">
<input
type="radio"
name={props.question}
id={`${props.question} ans2`}
onChange={toggleCheck}
checked={checked === `${props.question} ans2`}
correct={arr[1] === 3 ? "true" : "false"}
/>
<label htmlFor={`${props.question} ans2`}>{arr[1] === 3 ? decodeHtml(props.answer) : decodeHtml(props.incorrectAnswers[arr[1]])}</label>
</div>
<div className="card--answer">
<input
type="radio"
name={props.question}
id={`${props.question} ans3`}
onChange={toggleCheck}
checked={checked === `${props.question} ans3`}
correct={arr[2] === 3 ? "true" : "false"}
/>
<label htmlFor={`${props.question} ans3`}>{arr[2] === 3 ? decodeHtml(props.answer) : decodeHtml(props.incorrectAnswers[arr[2]])}</label>
</div>
<div className="card--answer">
<input
type="radio"
name={props.question}
id={`${props.question} ans4`}
onChange={toggleCheck}
checked={checked === `${props.question} ans4`}
correct={arr[3] === 3 ? "true" : "false"}
/>
<label htmlFor={`${props.question} ans4`}>{arr[3] === 3 ? decodeHtml(props.answer) : decodeHtml(props.incorrectAnswers[arr[3]])}</label>
</div>
</div>
</div>
)
}
export default Card;

React multiple checkbox with one check at a time

Hello I have question about how I can make user select one checkbox at a time. So for example, if there is three checkbox(none are selected when page loads) on react component and user select one checkbox, the other checkbox will not be checked unless user uncheck it. I am trying to use useref to make it to work... but seems like it is not working..
const refCheckBoxOne = useRef(null);
const refCheckBoxTwo = useRef(null);
const refCheckBoxThree = useRef(null);
const onchangefunction = (propertyname, value) => {
if(refcheckBoxOne.current.check){
refcheckBoxOne.current.check = false;
refcheckBoxOne.current.check = false;
}
}
<input id="one" ref={refCheckBoxOne} userefonchange={(e) => onchangefunction("checkboxOne",e.target.value) }/>
<input id="two" ref={refCheckBoxTwo} onchange={(e) => onchangefunction("checkboxTwo",e.target.value) }/>
<input id="three" ref={refCheckBoxThree} onchange={(e) => onchangefunction("checkboxThree",e.target.value) }/>
I have tried many ways to do it... but cant get it to work. I would be really appreciated if anyone can give me an idea on how to approach this kind of issue.
Thank you
If two items you can use this
const App = () => {
const [checked, setChecked] = React.useState(false);
const handleChange = () => {
setChecked(!checked);
};
return (
<div>
<label>
<input
type="checkbox"
checked={checked}
onChange={handleChange}
/>
</label>
</div>
);
};
If multiple value then use it
export default function App() {
const [checkedState, setCheckedState] = useState(
[false,false,false]
);
const handleOnChange = (position) => {
const updatedCheckedState = checkedState.map((item, index) =>
index === position ? !item : item
);
setCheckedState(updatedCheckedState);
};
return (
<div className="App">
<h3>Select Toppings</h3>
<ul className="toppings-list">
<li key=0>
<div className="toppings-list-item">
<div className="left-section">
<input
type="checkbox"
id=`custom-checkbox-1`
checked={checkedState[0]}
onChange={() => handleOnChange(0)}
/>
</div>
</div>
</li>
<li key=1>
<div className="toppings-list-item">
<div className="left-section">
<input
type="checkbox"
id=`custom-checkbox-1`
checked={checkedState[1]}
onChange={() => handleOnChange(1)}
/>
</div>
</div>
</li>
<li key=2>
<div className="toppings-list-item">
<div className="left-section">
<input
type="checkbox"
id=`custom-checkbox-2`
checked={checkedState[2]}
onChange={() => handleOnChange(2)}
/>
</div>
</div>
</li>
</ul>
</div>
If you have any question , Comment below here .

React form does not render the state values I put on constructor

I have a tab component with 2 tabs. The first tab contains a list of employees and a button that transfers you in the second tab (contact form) containing the data of the selected employee. In the first tab I create an object of an employee, send it in the second tab and in the second tab i set the state.name, state.surname with the object values.
The problem is that in order to load the data in the form I need to change back in the first tab and go to the second tab again.
The tabs component
import React from 'react';
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`simple-tabpanel-${index}`}
aria-labelledby={`simple-tab-${index}`}
{...other}
>
{value === index && (
<Box p={3}>
<Typography>{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.any.isRequired,
value: PropTypes.any.isRequired,
};
function a11yProps(index) {
return {
id: `simple-tab-${index}`,
'aria-controls': `simple-tabpanel-${index}`,
};
}
var importErg = new Boolean(false);
export function getImport(){
return importErg;
}
export const globalErg = {
onoma: "",
epitheto: ""
}
export function getGlobalErg(){
return globalErg;
}
async function getErgByeID(ErgEid){
globalErg.onoma = ""
globalErg.epitheto = ""
await fetch(URL+"/ergazomenoi?eid=eq."+ErgEid)
.then(response => {if(response.ok){
return response.json()
}
else {
alert('Something went wrong')
throw new Error('Something went wrong');
}
})
.then(data => {
globalErg.onoma = data[0].onoma
globalErg.epitheto = data[0].epitheto
}
)
}
export default function SimpleTabs() {
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
function more(ergID){
setValue(1);
getErgByeID(ergID);
}
}
return (
<div className="main">
<AppBar position="static" id = "topbar">
<Tabs value={value} onChange={handleChange}>
<Tab label="Employees" {...a11yProps(0)}/>
<Tab label="Contact" {...a11yProps(1)} />
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
<Table />
<Button style={{color: "#fff", background: "#111", marginRight: "2.5px", marginLeft:"2.5px", marginTop:"5px"}} onClick={() => more()}>
Contact
</Button>
</TabPanel>
<TabPanel value={value} index={1} id = 'tab'>
<Contact/>
</TabPanel>
</div>
);
}
the form component
import React, { Component, useEffect } from "react";
import {getGlobalErg} from "./Proswpiko-tabs";
class Personal_info extends Component {
constructor(props){
super(props);
let erg = getGlobalErg();
this.state = {
onoma: erg.onoma,
epitheto: erg.epitheto,
};
}
onomaChangeHandler = (event) => {
this.setState({onoma: event.target.value});
}
epithetoChangeHandler = (event) => {
this.setState({epitheto: event.target.value});
}
render() {
return (
<form onSubmit = {this.SubmitHandler}>
<div >
<p id = "topText" align = "center">
<h2>Contact info</h2>
</p>
<img id="top" src="top.png" alt=""></img>
<div id="form_container">
<form id="form" class="appnitro" method="post" action="">
<div class="form_description">
<h2>Personal info</h2>
</div>
<ul>
<li id = "li_3">
<label class="description" for="element_3" >Όνομα </label>
<span>
<input type ="text" id="nameInput" name= "nameInput" class="element text" maxLength="255" size="15" onChange={this.onomaChangeHandler} value = {this.state.onoma} required/>
<label>Name</label>
</span>
<span>
<input type ="text" id="surNameInput" name= "surNameInput" class="element text" maxLength="255" size="14" onChange={this.epithetoChangeHandler} value = {this.state.epitheto} required/>
<label>Surname</label>
</span>
</li>
</ul>
</form>
<div id="footer">
</div>
</div>
<img id="bottom" src="bottom.png" alt=""></img>
</div>
</form>
);}}
export default Personal_info;
It seems that since the setState func is async It didnt had time to fill the imput boxes.
Solution: Added setTimeout and now everything works fine

Hide other previous div/dropdown React

I am wanting to hide other sibling divs (dropdowns in my case) when I click the statusPillDropdown
so far I click I am setting the status to true and opening the div,
{DropDown ${toggleStatusDropdown ? "open": ""}}
Do I just need to set the state to false for previously opened ones? Not sure how to do this.
thank you
import React, { useState } from "react";
import "./StatusPillDropdown.scss";
function StatusPillDropdown({
cellData,
rowItemId,
onStatusPillDropdownChange
}) {
const [toggleStatusDropdown, setToggleStatusDropdown] = useState();
const toggleDropdown = (action, rowItemId, e) => {
if (action === "pillClick") {
setToggleStatusDropdown(true);
} else {
onStatusPillDropdownChange(rowItemId, e.target.getAttribute("value"));
setToggleStatusDropdown(false);
}
};
const renderstatusPillDropdown = (cellData, rowItemId) => (
<React.Fragment>
<span
className="statusPillDropdown"
onClick={() => toggleDropdown("pillClick", rowItemId)}
>
<span className={`status-pill ${cellData.type}`}>{cellData.text}</span>
</span>
<div className="status">
<div className="dropdown-container">
<div className={`DropDown ${toggleStatusDropdown ? "open" : ""}`}>
<ul>
<li
value="Information only"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span></span>Information only
</li>
<li
value="Unresolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="unresolved"></span>Unresolved
</li>
<li
value="Partially Resolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="partyResolved"></span>Partially Resolved
</li>
<li
value="Fully Resolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="resolved"></span>Fully Resolved
</li>
</ul>
</div>
</div>
</div>
</React.Fragment>
);
return (
<React.Fragment>
{renderstatusPillDropdown(cellData, rowItemId)}
</React.Fragment>
);
}
export default StatusPillDropdown;

Dynamically adding button to div ReactJS?

Ok so here's my code:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
var uuid = require("uuid-v4");
// Generate a new UUID
var myUUID = uuid();
// Validate a UUID as proper V4 format
uuid.isUUID(myUUID); // true
var questionNum = 0;
class App extends Component {
constructor(props) {
super(props);
this.state = {
key: uuid(),
title: "",
author: "",
questions: [],
answers: []
};
this.handleChange = this.handleChange.bind(this);
this.addQuestion = this.addQuestion.bind(this);
this.removeItem = this.removeItem.bind(this)
}
componentDidMount() {
// componentDidMount() is a React lifecycle method
this.addQuestion();
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
removeItem (index) {
questionNum--;
this.setState(({ questions }) => {
const mQuestions = [ ...questions ]
mQuestions.splice(index, 1)
return { questions: mQuestions }
})
this.setState(({ answers }) => {
const mAnswers = [ ...answers]
mAnswers.splice(index, 4)
return { answers: mAnswers}
})
console.log(
"answers",
this.state.answers,
"questions",
this.state.questions,
questionNum,
this.state.title,
this.state.author
);
}
addQuestion() {
questionNum++;
this.setState(previousState => {
const questions = [
...previousState.questions,
<input
type="text"
onChange={this.handleChange}
name="question"
key={uuid()}
/>
];
const answers = [
...previousState.answers,
];
for (var i = 0; i < 4; i++) {
answers.push(
<input
type="checkbox"
name={uuid()}>
<input
type="text"
onChange={this.handleChange}
name={uuid()}
/>
</input>
);
}
return { questions, answers };
});
console.log(
"answers",
this.state.answers,
"questions",
this.state.questions,
questionNum,
this.state.title,
this.state.author
);
}
render() {
return (
<div className="App">
<div>
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Quiz Form 3.0</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
<div className="formDiv">
<form>
<div className="Intro">
Give your Quiz a title:{" "}
<input
type="text"
value={this.state.title}
onChange={this.handleChange}
name="title"
/>
<br />
Who's the Author?{" "}
<input
type="text"
value={this.state.author}
onChange={this.handleChange}
name="author"
/>
<br />
<br />
</div>
<div className="questions">
<div className="questions">
Now let's add some questions... <br />
<ol>
{this.state.questions.map(question => {
return (
<li>
<div key={uuid()}>
Question
{question}<br />
Answer Choices<br />
{Array.from({ length: 4 }, () => (
<input type="text" key={uuid()} onChange={this.handleChange} />
))}
</div>
</li>
);
})}
</ol>
</div>
{
// This is what it would look like for the structure
// I proposed earlier.
// this.state.questions.map((question) {
// return (
// <div>{question.quesion}</div>
// {
// question.answers.map((answer) => {
// return (<div>{answer}</div>);
// })
// }
// );
// })
// This would output all questions and answers.
}
</div>
</form>
<button id="addQuestionButton" onClick={this.addQuestion}>Add Question</button>
{ this.state.questions.map((question, index) => {
return <button key={uuid()} onClick={ () => this.removeItem(index) }>Remove Question</button>
}) }
</div>
</div>
);
}
}
export default App;
Ok so here's a link to a quick video demonstrating what it does as of now. In the video you can see the Remove Question buttons that are created (at the bottom of the form) each time a question is added. I would like to have each question's Remove Question button be next to it/in the same div. I'm not entirely sure how I would go about doing this. Any thoughts?
UPDATE: Ok so I have put the buttons inside of the same div with the actual question, but I realized that i am adding a button for each object in the array. Which means that when a question is added a button to remove it is added to every question on the form. I need to make it so it does not .map this. I'm not entirely sure what other function I will do for this, maybe I don't even need a function. I will try my best to work it out. Here's the updated code (some of it):
<div className="questions">
Now let's add some questions... <br />
<ol>
{this.state.questions.map(question => {
return (
<li>
<div key={uuid()}>
Question
{question}<br />
{
this.state.questions.map((question, index) => {
return <button key={uuid()} onClick={ () => this.removeItem(index) }>Remove Question</button>
})
}
Answer Choices<br />
{Array.from({ length: 4 }, () => (
<div>
<input type="checkbox" />
<input type="text" key={uuid()} onChange={this.handleChange} />
</div>
))}
</div>
</li>
);
})}
</ol>
</div>
Something like this...
<ol>
{this.state.questions.map((question, index) => {
return (
<li>
<div key={uuid()}>
Question
{question}<br />
<button onClick={ () => this.removeItem(index) }>
Remove Question
</button>
Answer Choices<br />
{Array.from({ length: 4 }, () => (
<div key={uuid()}>
<input type="checkbox" />
<input type="text" onChange={this.handleChange} />
</div>
))}
</div>
</li>
);
})}
</ol>

Categories

Resources