0

I have a table which contains another table in reactjs. I've inserted a button inside each row of the outer table and when I clicked this I trigger an action for showing the nested table. My code is like this:

{slipsList.map((slip, i) =>
              <tbody>
                <tr key={i}>
                  <td className="table-sticky--first-col">
                    {slip.confirmationDate}
                    <button
                      type="button"
                      onClick={() => hideButtonClicked()}
                    >{i}</button>
                  </td>
                  <td>
                    {slip.slipNumber}
                  </td>
                  <td>
                    {slip.country}
                  </td>
                  <td>
                    {slip.side}
                  </td>
                  <td>
                    {slip.grossAmount}
                  </td>
                  <td>
                    {slip.commission}
                  </td>
                  <td>
                    {slip.feesPerStampDuty}
                  </td>
                  <td>
                    {slip.tax}
                  </td>
                  <td>
                    {slip.netAmount}
                  </td>
                  <td>
                    {slip.netAmountEuro}
                  </td>
                </tr>
                <tr
                  className={classnames({ hide_element: slipsHide })}
                >
                  <td colSpan="10">
                    {renderInside(slip)}
                  </td>
                </tr>
              </tbody>
            )}

When a user clicks the button in a row this row must collapse. My problem is that with my implementation when I click the button all the rows of the table are collapsed. My renderInside function is the following:

<tbody>
          <tr>
            <td>
              {renderInstrumentInfo(slip.prodType,
              slip.symbol, slip.exchange,
              slip.country, slip.name)}
            </td>
            <td>{slip.type}</td>
            <td>{slip.quantity}</td>
            <td>{slip.price}</td>
            <td>{slip.amount}</td>
          </tr>
        </tbody>

Any ideas?

2
  • what is slipsHide in this line, className={classnames({ hide_element: slipsHide })} . Can you show ur constructor ? Commented Apr 11, 2017 at 9:53
  • slipHide is a boolean value. When i click the button it becomes true or false and the hide_element class is applied or not Commented Apr 11, 2017 at 10:00

2 Answers 2

1

Passing the index of the row that you want to show or hide will help

Set up an onClick method and pass the index like

<button
  type="button"
  onClick={() => hideButtonClicked(i)}
>{i}</button>

And in redux mapDispatchToProps(), pass an argument to get the index and pass it like

mapStateToProps = dispatch => (
      {hideButtonClicked: (index) => {
                dispatch(expandCollapseClicked('slips', index))
           }
      })
Sign up to request clarification or add additional context in comments.

9 Comments

With that way i need to redefine my action export function expandCollapseClicked(component) { return { type: EXPAND_COLLAPSE_CLICKED, payload: { component } }; }
Yes you will need to do that so that you can handle individual rows differently
Is there a more rapid way to achieve this? Maybe call className inside the other function. I dont want to change the expand collapse action because i use it in many components
You can simply create a new function that does it for you and whose implementation is the same as expandCollapse function and use that,
I made it but it doesnt work, the className={classnames({ hide_element: slipsHide[i] })} applies the value true or false to all the rows of the nestred table
|
0

Reason is, you are using single bool for all the rows, instead of that use an array of bool values, each value for each row, like this:

<tr
   className={classnames({ hide_element: slipsHide[i] })}
>

And onClick of button change only that particular bool, not the all values. To update the specific value you need to pass the index of each item into onClick method, like this:

<button
  type="button"
  onClick={() => hideButtonClicked(i)}
>{i}</button>

Now use this index in hideButtonClicked method:

hideButtonClicked(index){
  //now update only slipsHide[index]
}

5 Comments

I've thought of your idea but i have a problem. My hideButtonClicked is generated through mapDispatchToProps like this: const mapDispatchToProps = dispatch => ( { hideButtonClicked: () => { dispatch(expandCollapseClicked('slips')); } } );. How to add i when i dispatch it? Sorry for the foolish question but i'm pretty new to react and js :)
and slipHide through mapStateToProps like this: slipsHide: userSettingsState(state).get('slipsHide')
@Shubham i don't know much about redux, answered this ques, he is using const mapDispatchToProps help him to pass index in onclick method, check the above comment how he is handling the events.
change definition to mapStateToProps = dispatch => ({hideButtonClicked: (index) => {dispatch(expandCollapseClicked('slips', index))}})
please add that in a separate answer.

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.