ZachDLR
ZachDLR

Reputation: 11

Enabling a single button from an array of data enclosing in .map

Need your help with regards to enabling button when click INSIDE .map

Here's the data from backend:

file :[ { id: 1 color: orange, shape: triangle
} { id: 2 color: blue, shape: circle
} { id: 3 color: red, shape: rectangle
} ]

And this is the file rendered in .map way:

{file.map(file => (
  `<div>
      <a
        onClick={() => this.downloadFile(file)}
        href="javascript:void(0);"
      >
        {file.fileName}
      </a>

</div>

        <Button
          onClick={() => this.submit()}
          disabled={should be enabled when click}
        >
          submit
      </Button>

))}

In UI, it looks like this:

LINK--------------Button (this is disabled)
LINK--------------Button (this is disabled)
LINK--------------Button (this is disabled)

What i need is a function that when i click the first LINK, it only enable the first button beside it, what i have now is when i click the first LINK, it enables all the button

Please help. Thanks

Upvotes: 1

Views: 443

Answers (3)

Drew Reese
Drew Reese

Reputation: 202605

Add an active button index to your state

this.state = {
  // ... any other state
  activeButtonIndex: null,
};

When a button is clicked set the activeButtonIndex to the mapped index of the button. Also use the activeButtonIndex to compare against the current mapping index and disable the button when they match.

{file.map((file, index) => (
  <div>
    <a
      onClick={() => this.downloadFile(file)}
      href="javascript:void(0);"
    >
      {file.fileName}
    </a>
    <Button
      onClick={() => {
        this.submit();
        this.setState({ activeButtonIndex: index }); // <-- set active index
      }}
      disabled={index === this.state.activeButtonIndex} // <-- check active index
    >
      submit
    </Button>
  </div> 
))}

Edit to allow multiple active

Add an active button index object to your state

this.state = {
  // ... any other state
  activeButtonIndex: {},
};

When a button is clicked add the mapped index to the activeButtonIndex object. Also use the activeButtonIndex object to compare against the current mapping index and disable the button when that index is in the activeButtonIndex object.

{file.map((file, index) => (
  <div>
    <a
      onClick={() => this.downloadFile(file)}
      href="javascript:void(0);"
    >
      {file.fileName}
    </a>
    <Button
      onClick={() => {
        this.submit();
        this.setState(prevState => ({
          activeButtonIndex: {
            ...prevState.activeButtonIndex, // <-- copy existing state
            [index]: true, // <-- set active index
          },
        }));
      }}
      disabled={this.state.activeButtonIndex[index]} // <-- check active index
    >
      submit
    </Button>
  </div> 
))}

Upvotes: 1

Joe Abdel Sater
Joe Abdel Sater

Reputation: 107

Hopefully you are storing your loaded data in state. You should need an individual toggle for each button

state = {
    data : []
}
this.apiCallToGetData().then(res => {
    //set all buttons to disabled by default
   res.map(r => {r.disabled = true;})
  this.setState({data: res})
});

In your HTML, make the disabled property dynamic and pass the index to the downloadFile function:

{file.map((file, index) => (
  <div>
    <a
      onClick={() => this.downloadFile(file, index)}
      href="javascript:void(0);"
    >
      {file.fileName}
    </a>
    <Button
        onClick={() => this.submit()}
        disabled={file.disabled}
      >
              submit
     </Button>
  </div> 
))}

And finally, modify the downloadFile function to update the button's disabled state on click

downloadFile = (file, index) => {
 let freshFiles = this.state.data;
 freshFiles[index].disabled = false;
 this.setState({data : freshFiles});

   //the rest of your code
}

Upvotes: 0

Kai Sheng Tung
Kai Sheng Tung

Reputation: 430

You should store the state when the first link is clicked. It can be stored in localStorage or cookie. Then you'll have to retrieve it in your component.

Or, if your link is not redirecting users to another page, then you can simply store the state in your component. For example,

this.state = {
  isClicked = true
}

Upvotes: 0

Related Questions