Binny.H
Binny.H

Reputation: 83

Toggle display specific element inside map function onClick

I have a plus sign which onClick switches to Minus sign. With that, a list of grades is also displayed based on toggle.

Currently when I click on the plug sign, all the elements expand displaying list for all students. I want to only toggle the list for the specific student.

The data is being pulled from an API then being displayed.

class Home extends Component {
  constructor(props) {
    super(props);
    this.state = {
      students: [],
      search: "",
      display: false
    };
  }

_iconOnClick = event => {
    this.state.display ? this.setState({ display: false }) : this.setState({ display: true })
    ;
  };

 _renderDataFromAPI = () => {
//search filter
    let filteredName = this.state.students.filter(student => {
      return (
        student.firstName
          .toLowerCase()
          .includes(this.state.search.toLowerCase()) ||
        student.lastName.toLowerCase().includes(this.state.search.toLowerCase())
      );
    });

    return filteredName.map((student,i) => {
      let average =
        student.grades.reduce((x, y) => parseInt(x) + parseInt(y)) /
        student.grades.length;
      return (
        <div key={i}>
          <div className="data">
            <img className="img" src={student.pic} align="left" />
            {this.state.display ? (
              <FontAwesomeIcon
                style={{
                  float: "right",
                  fontSize: "30px",
                  marginRight: "40px"
                }}
                icon="minus"
                onClick={this._iconOnClick}
              />
            ) : (
              <FontAwesomeIcon
                style={{
                  float: "right",
                  fontSize: "30px",
                  marginRight: "40px"
                }}
                icon="plus"
                onClick={this._iconOnClick}
              />
            )}

            <h1>
              {student.firstName.toUpperCase()} {student.lastName.toUpperCase()}
            </h1>
            <p>Email: {student.email}</p>
            <p>Company: {student.company}</p>
            <p>Skill: {student.skill}</p>
            <p>Average: {average}%</p>
            <br />
            {this.state.display ? (
              <div >
                {student.grades.map((grade, i) => {
                  return (
                    <p key={i}>
                      Test {i + 1}: {grade}%
                    </p>
                  );
                })}
              </div>
            ) : (
              <div />
            )}
          </div>
          <hr style={{ borderColor: "#e2e1e1" }} />
        </div>
      );
    });
  };

Upvotes: 0

Views: 616

Answers (1)

below-1
below-1

Reputation: 374

Move the display to each student.

let dataFromAPI = getDataFromAPI();
this.setState({ 
    students: dataFromAPI.map(
        student => Object.assign(student, { display: false }) 
});

Display the list...

 {student.display ? (
   <div >
     {student.grades.map((grade, i) => { ...

Toggle the show/hide

_iconOnClick = id => {
   let students = this.students.map(s => {
     if (id == s.id) {
       return Object.assign(s, { display: !s.display });
     }
     return s;
   });
   this.setState({ students });
};

...

<FontAwesomeIcon
  style={{
    float: "right",
    fontSize: "30px",
    marginRight: "40px"
  }}
  icon="minus"
  onClick={this._iconOnClick(student.id)} />

Upvotes: 2

Related Questions