1

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.

2

1 Answer 1

1

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>
    );
}
Sign up to request clarification or add additional context in comments.

12 Comments

Thank you, that really worked. One last question. I am having a useState object that holds this groupDetails array: const [state, setState] = React.useState({ fullName: "", phoneNo: " ", email: "", idProof: "",bookingId: "", bookingDate: "", detailsOfPeople: groupDetails, }); and within useEffect hook I am doing this useEffect(() => { setGroupDetails(groupDetails); setState(state); }, [state, groupDetails]); now the problem Is the values we just took into that groupDetails array are not reflecting withing the state when I do console.log(state);
tough to understand by reading comment. can you please post another question with sample code and give me the link?
Also, please make it answer by clicking on the tick sign as it worked for you
ok thank you for letting me know to tick sign, as I didn't know that. how should I share the link with you?
you can create a new question with proper example as you did it for this question. then copy the url of that new question and pasted it here as an comment
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.