Reputation: 184
I am having 3 materialUI TextFields which I want to render n number of times (that n will be a integer input from user before rendering the form field, here I stored it in a variable named groupMembersCount). I am using functional component in ReactJS defining an array with useState hooks as:
const [groupDetails, setGroupDetails] = React.useState([
{ fullName: "", phoneNo: "", gender: "" },
]);
This will be my main array to hold all the 3 values(user input) at their respective indexes. I tried returning those 3 materialUI TextField dynamically by this method:
{Array.apply(null, { length: groupMembersCount }).map(
(e, i) => (
<div key={i}>
<strong>Member #{i + 1}</strong>
<div className="getIndex" name={i + 1}>
<TextField
id={Math.random()}
name="Name"
variant="outlined"
margin="none"
label="Name"
onChange={handleGroupName}
/>
<TextField
id={Math.random()}
name="phoneNo"
variant="outlined"
margin="none"
label="Mobile Number"
onChange={handleGroupPhoneNo}
/>
<TextField
id={Math.random()}
name="gender"
variant="outlined"
margin="none"
label="Gender"
onChange={handleGroupGender}
select
>
<option value="MALE">Male</option>
<option value="FEMALE">Female</option>
<option value="OTHER">Other</option>
</TextField>
</div>
</div>
)
)}
Now in the name handler handleGroupName I am doing this to get the div(to get index [from its name attribute] which stores index to push this value in main array groupDetails):
const handleGroupName = (event) => {
let elem = document.getElementsByClassName("getIndex"); // get div
for (var i = 0; i < groupMembersCount; i++) {
console.log("index is: ", elem[i].getAttribute('name')); // get the index number
}
};
After doing all this I am having issues in few things: 1. One of the form fields (TextField) with gender in name attribute, I'm unable to use select to create a dropdown (writing what is shown here causes a blank screen) so I commented it out. 2. In handleGroupName handler within the for loop it shows the error as: UserDetails.jsx:434 Uncaught TypeError: Cannot read property 'getAttribute' of undefined. 3. I'm new to react functional component, not much experience in it, can anyone suggest some better ways to get values from those form fields for every render and club those as an object and store at different index in the main array, the structure of main array groupDetails defines how it should look like at the end.
Upvotes: 1
Views: 1669
Reputation: 5854
Please try this example where I take an input that define number of member
in the group. Then it shows number of input groups
(name, phone and gender). After filling the info if you click on the Show
button, you will see the results.
import TextField from "@material-ui/core/TextField";
import React, {useState} from "react";
import Select from "@material-ui/core/Select";
import Button from "@material-ui/core/Button";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Typography from "@material-ui/core/Typography";
export default function DynamicGroupMember() {
const [groupMembersCount, setGroupMembersCount] = useState(0);
const [show, setShow] = useState(false);
const [groupDetails, setGroupDetails] = useState([
{fullName: "", phoneNo: "", gender: ""},
]);
function handleChange(event, index) {
console.log(event.target.value, index);
let newArr = [...groupDetails]; // copying the old datas array
let item = newArr[index];
item = {...item, [event.target.name]: event.target.value};
newArr[index] = item;
setGroupDetails(newArr);
}
return (
<div>
Number of Group: <TextField name="groupMembersCount" onChange={(event) => {
setGroupMembersCount(event.target.value)
}}/>
{Array.apply(null, {length: groupMembersCount}).map(
(e, i) => (
<div key={i}>
<strong>Member #{i + 1}</strong>
<div className="getIndex" name={i + 1}>
<TextField
id={`name${i + 1}`}
name="fullName"
variant="outlined"
margin="none"
label="Name"
onChange={(event) => {
handleChange(event, i)
}}
/>
<TextField
id={`phoneNo${i + 1}`}
name="phoneNo"
variant="outlined"
margin="none"
label="Mobile Number"
onChange={(event) => {
handleChange(event, i)
}}
/>
<Select
id={`gender${i + 1}`}
name="gender"
variant="outlined"
margin="none"
label="Gender"
onChange={(event) => {
handleChange(event, i)
}}
>
<option value="MALE">Male</option>
<option value="FEMALE">Female</option>
<option value="OTHER">Other</option>
</Select>
</div>
</div>
)
)}
<Button onClick={() => {
setShow(true)
}}>Show</Button>
{
show ?
groupDetails.map(member =>
<Card>
<CardContent>
<Typography color="textSecondary" gutterBottom>
{member.fullName}
</Typography>
<Typography variant="h5" component="h2">
{member.phoneNo}
</Typography>
<Typography color="textSecondary">
{member.gender}
</Typography>
</CardContent>
</Card>) : null
}
</div>
);
}
Upvotes: 1