javascript - How to expand and collapse the table rows in plain react js. Show only one row if the description of the row is mul

I am working on the table content which has 5 rows . few rows content description is same so I need to

I am working on the table content which has 5 rows . few rows content description is same so I need to show only one row in this case and give expan button. when expand button is clicked it should show all the rows which has the same associated description. I am pasting the screenshot which I got as output .

In the above screenshot I've got the "-" button for all the rows which has same description. but I need only one "-"(collapse) button for "paytm" and one "-"button for "Paypal". and when they are clicked only one paytm, PayPal should be displayed.

     let rows = [
          {
            id: { value: '' },
            description: { value: 'Paytm' },       
            DueDate: { value: '04/03/2020' },  
          },
          {
            id: { value: '' },
            description: { value: 'paypal' }, 
            DueDate: { value: '04/04/2021' }
          },
          {
            id: { value: '' },
            description: { value: 'paypal' }, 
            DueDate: { value: '04/03/2020' }
          },
          {
            id: { value: '' },
            description: { value: 'Paytm' },
            DueDate: { value: '04/03/2021' }
          },
          {
            id: { value: '' },
            description: { value: 'Gpay' }, 
            DueDate: { value: '04/03/2020' }
          },
        ];

I am showing the table based on the lasted date and check if there exists any multiple same descriptions and putting them all in one object.

    const descriptionSortedArray = rows.reduce((acc, current) => {
          acc[current.description.value] = [
            ...(acc[current.description.value] || []),
            current,
          ];
          return acc;
        }, {});
    
        console.log(descriptionSortedArray);

and transforming the object based on latest date

     const transformedRows = Object.keys(descriptionSortedArray).reduce(
          (acc, current) => {
            acc[current] = sortRowsByDate(descriptionSortedArray[current]);
            return acc;
          },
          {}
        );
        // console.log(Object.keys(descriptionSortedArray));
        console.log({ transformedRows });

and getting the key values for them by using object.keys and mapping over them.

    x.[paytm:[], Gpay:[], PayPal :[]];

based on the inner array key length I am showing button (expand and collapse)if x[paytm]>1 ?show button: without button

code is below

    import React, { Component } from 'react';
    import './style.css';
    
    export default class App extends React.Component {
      render() {
        let rows = [
          {
            id: { value: '' },
            description: { value: 'Paytm' },       
            DueDate: { value: '04/03/2020' },  
          },
          {
            id: { value: '' },
            description: { value: 'paypal' }, 
            DueDate: { value: '04/04/2021' }
          },
          {
            id: { value: '' },
            description: { value: 'paypal' }, 
            DueDate: { value: '04/03/2020' }
          },
          {
            id: { value: '' },
            description: { value: 'Paytm' },
            DueDate: { value: '04/03/2021' }
          },
          {
            id: { value: '' },
            description: { value: 'Gpay' }, 
            DueDate: { value: '04/03/2020' }
          },
        ];
    
        const descriptionSortedArray = rows.reduce((acc, current) => {
          acc[current.description.value] = [
            ...(acc[current.description.value] || []),
            current,
          ];
          return acc;
        }, {});
    
        console.log(descriptionSortedArray);
    
        const sortRowsByDate = (rows) =>
          rows.sort(
            (a, b) => new Date(b.DueDate.value) - new Date(a.DueDate.value)
          );
    
        const transformedRows = Object.keys(descriptionSortedArray).reduce(
          (acc, current) => {
            acc[current] = sortRowsByDate(descriptionSortedArray[current]);
            return acc;
          },
          {}
        );
        // console.log(Object.keys(descriptionSortedArray));
        console.log({ transformedRows });
        
    
        return (
          <div>
            <table>
              <tr>
                <th>id</th>
                <th>description</th>
                <th>duedate</th>
                <th></th>
               
              </tr>
              {Object.keys(transformedRows).map((rowKey) => {
                // console.log("rowKey===", rowKey)
                //   console.log(transformedRows[rowKey])
                return (
                  <tbody>
                    {transformedRows[rowKey].length > 1
                      ? transformedRows[rowKey].map((obj) => (
                          <tr>
                            <td>{obj.id.value}</td>
                            <td>{obj.description.value}</td>  
                            <td>{obj.DueDate.value}</td>
                            <td>{<button>-</button>}</td>
                                                  </tr>
                        ))
                      : transformedRows[rowKey].map((obj) => (
                          <tr>
                            <td>{obj.id.value}</td>
                            <td>{obj.description.value}</td> 
                            <td>{obj.DueDate.value}</td>
                            <td></td>
                          </tr>
                        ))}
                  </tbody>
                );
              })}
            </table>
          </div>
        );
      }
    }

Please help in this. I need to show only one collapse button for the rows having same description(paytm is repeated show them only in one row give "expand" and "collapse" button). when even button is clicked it should be toggled. Please help

I am working on the table content which has 5 rows . few rows content description is same so I need to show only one row in this case and give expan button. when expand button is clicked it should show all the rows which has the same associated description. I am pasting the screenshot which I got as output .

In the above screenshot I've got the "-" button for all the rows which has same description. but I need only one "-"(collapse) button for "paytm" and one "-"button for "Paypal". and when they are clicked only one paytm, PayPal should be displayed.

     let rows = [
          {
            id: { value: '' },
            description: { value: 'Paytm' },       
            DueDate: { value: '04/03/2020' },  
          },
          {
            id: { value: '' },
            description: { value: 'paypal' }, 
            DueDate: { value: '04/04/2021' }
          },
          {
            id: { value: '' },
            description: { value: 'paypal' }, 
            DueDate: { value: '04/03/2020' }
          },
          {
            id: { value: '' },
            description: { value: 'Paytm' },
            DueDate: { value: '04/03/2021' }
          },
          {
            id: { value: '' },
            description: { value: 'Gpay' }, 
            DueDate: { value: '04/03/2020' }
          },
        ];

I am showing the table based on the lasted date and check if there exists any multiple same descriptions and putting them all in one object.

    const descriptionSortedArray = rows.reduce((acc, current) => {
          acc[current.description.value] = [
            ...(acc[current.description.value] || []),
            current,
          ];
          return acc;
        }, {});
    
        console.log(descriptionSortedArray);

and transforming the object based on latest date

     const transformedRows = Object.keys(descriptionSortedArray).reduce(
          (acc, current) => {
            acc[current] = sortRowsByDate(descriptionSortedArray[current]);
            return acc;
          },
          {}
        );
        // console.log(Object.keys(descriptionSortedArray));
        console.log({ transformedRows });

and getting the key values for them by using object.keys and mapping over them.

    x.[paytm:[], Gpay:[], PayPal :[]];

based on the inner array key length I am showing button (expand and collapse)if x[paytm]>1 ?show button: without button

code is below

    import React, { Component } from 'react';
    import './style.css';
    
    export default class App extends React.Component {
      render() {
        let rows = [
          {
            id: { value: '' },
            description: { value: 'Paytm' },       
            DueDate: { value: '04/03/2020' },  
          },
          {
            id: { value: '' },
            description: { value: 'paypal' }, 
            DueDate: { value: '04/04/2021' }
          },
          {
            id: { value: '' },
            description: { value: 'paypal' }, 
            DueDate: { value: '04/03/2020' }
          },
          {
            id: { value: '' },
            description: { value: 'Paytm' },
            DueDate: { value: '04/03/2021' }
          },
          {
            id: { value: '' },
            description: { value: 'Gpay' }, 
            DueDate: { value: '04/03/2020' }
          },
        ];
    
        const descriptionSortedArray = rows.reduce((acc, current) => {
          acc[current.description.value] = [
            ...(acc[current.description.value] || []),
            current,
          ];
          return acc;
        }, {});
    
        console.log(descriptionSortedArray);
    
        const sortRowsByDate = (rows) =>
          rows.sort(
            (a, b) => new Date(b.DueDate.value) - new Date(a.DueDate.value)
          );
    
        const transformedRows = Object.keys(descriptionSortedArray).reduce(
          (acc, current) => {
            acc[current] = sortRowsByDate(descriptionSortedArray[current]);
            return acc;
          },
          {}
        );
        // console.log(Object.keys(descriptionSortedArray));
        console.log({ transformedRows });
        
    
        return (
          <div>
            <table>
              <tr>
                <th>id</th>
                <th>description</th>
                <th>duedate</th>
                <th></th>
               
              </tr>
              {Object.keys(transformedRows).map((rowKey) => {
                // console.log("rowKey===", rowKey)
                //   console.log(transformedRows[rowKey])
                return (
                  <tbody>
                    {transformedRows[rowKey].length > 1
                      ? transformedRows[rowKey].map((obj) => (
                          <tr>
                            <td>{obj.id.value}</td>
                            <td>{obj.description.value}</td>  
                            <td>{obj.DueDate.value}</td>
                            <td>{<button>-</button>}</td>
                                                  </tr>
                        ))
                      : transformedRows[rowKey].map((obj) => (
                          <tr>
                            <td>{obj.id.value}</td>
                            <td>{obj.description.value}</td> 
                            <td>{obj.DueDate.value}</td>
                            <td></td>
                          </tr>
                        ))}
                  </tbody>
                );
              })}
            </table>
          </div>
        );
      }
    }

Please help in this. I need to show only one collapse button for the rows having same description(paytm is repeated show them only in one row give "expand" and "collapse" button). when even button is clicked it should be toggled. Please help

Share Improve this question edited Feb 4, 2022 at 7:55 Amila Senadheera 13.3k16 gold badges29 silver badges46 bronze badges asked Feb 4, 2022 at 7:53 SathishSathish 681 gold badge2 silver badges9 bronze badges 5
  • 1 stackblitz./edit/react-6dt9gp?file=src%2FApp.js I've implemented an exapmle here, if it solves your problem let me to post it as answer. – Saeed Shamloo Commented Feb 4, 2022 at 8:37
  • @Saeed Shamloo it works for me. It is appreciated if you can help me with the need of both paytm and paypal es under same group so there should not be any "border" between them when expanded. – Sathish Commented Feb 4, 2022 at 11:07
  • I didn't understand exactly what you mean, but I made some changes in the example. please check it out. – Saeed Shamloo Commented Feb 4, 2022 at 12:07
  • thanks for trying, but still when I clicked on expand paytm, paypal rows also are loading. previous one was fine. It was almost full filling my requirement . I will try for border collapse. Please upload previous answer. – Sathish Commented Feb 4, 2022 at 14:05
  • I reverted to previous one. – Saeed Shamloo Commented Feb 4, 2022 at 14:14
Add a ment  | 

2 Answers 2

Reset to default 3

You can keep another field called visible along with your data array and toggle its value when clicked on the button.

  1. Define a state to store the transformedRows
  state = {
    transformedRows: {}
  };
  1. Do the transformation like below in ponentDidMount.
  ponentDidMount = () => {
    const descriptionSortedArray = rows.reduce((acc, current) => {
      acc[current.description.value] = {
        ...acc[current.description.value],
        data: [...(acc[current.description.value]?.["data"] ?? []), current],
        visible: false
      };
      return acc;
    }, {});

    const sortRowsByDate = (rows) =>
      rows.sort(
        (a, b) => new Date(b.DueDate.value) - new Date(a.DueDate.value.data)
      );

    const transformedRows = Object.keys(descriptionSortedArray).reduce(
      (acc, current) => {
        acc[current] = {
          ...descriptionSortedArray[current],
          data: sortRowsByDate(descriptionSortedArray[current]["data"])
        };
        return acc;
      },
      {}
    );
    this.setState({ transformedRows });
  };
  1. Toggle the visible state when clicking on the button.
  handleToggle = (entry, visibility) => {
    this.setState((prevState) => {
      return {
        ...prevState,
        transformedRows: Object.fromEntries(
          Object.entries(prevState.transformedRows).map(([key, value]) => {
            if (key === entry) {
              return [key, { ...value, visible: visibility }];
            } else {
              return [key, value];
            }
          })
        )
      };
    });
  };
  1. Render rows as below.

<tbody>
    {Object.entries(transformedRows).map(([key, { data, visible }]) => {
        if (data.length > 1) {
            return data.map((item, index) => (
                <tr>
                    {(index === 0 || (index >= 1 && visible)) && (
                        <>
                            <td>{item.id.value}</td>
                            <td>{item.description.value}</td>
                            <td>{item.DueDate.value}</td>
                        </>
                    )}
                    {index === 0 && (
                        <td>
                            {
                                <button
                                    onClick={() => {
                                        this.handleToggle(key, !visible);
                                    }}
                                >
                                    toggle
                                </button>
                            }
                        </td>
                    )}
                </tr>
            ));
        } else {
            return data.map(item => (
                <tr>
                    <td>{item.id.value}</td>
                    <td>{item.description.value}</td>
                    <td>{item.DueDate.value}</td>
                </tr>
            ));
        }
    })}
</tbody>

Create an accordion ponent as follow:

React accordion

Then use it as follow:

return (
    <div>
        <table>
            <thead>
                <tr>
                    <th>id</th>
                    <th>description</th>
                    <th>duedate</th>
                    <th></th>
                </tr>
            </thead>
            {Object.keys(transformedRows).map((rowKey) => {
                // console.log("rowKey===", rowKey)
                //   console.log(transformedRows[rowKey])
                console.log(rowKey);
                return (
                    <tbody key={rowKey}>
                        {transformedRows[rowKey].length > 1 ? (
                            <tr>
                                <td colSpan="4">
                                    <Accordion label={rowKey}>
                                        {transformedRows[rowKey].map((obj) => (
                                            <div key={obj.id.value}>
                                                <span>{obj.id.value}</span>
                                                <span>{obj.description.value}</span>
                                                <span>{obj.DueDate.value}</span>
                                                <span>{<button>-</button>}</span>
                                            </div>
                                        ))}
                                    </Accordion>
                                </td>
                            </tr>
                        ) : (
                            transformedRows[rowKey].map((obj) => (
                                <tr key={obj.id.value}>
                                    <td>{obj.id.value}</td>
                                    <td>{obj.description.value}</td>
                                    <td>{obj.DueDate.value}</td>
                                    <td></td>
                                </tr>
                            ))
                        )}
                    </tbody>
                );
            })}
        </table>
    </div>
);

Full code:

let rows = [
    {
        id: { value: '1' },
        description: { value: 'Paytm' },
        DueDate: { value: '04/03/2020' },
    },
    {
        id: { value: '2' },
        description: { value: 'paypal' },
        DueDate: { value: '04/04/2021' },
    },
    {
        id: { value: '3' },
        description: { value: 'paypal' },
        DueDate: { value: '04/03/2020' },
    },
    {
        id: { value: '4' },
        description: { value: 'Paytm' },
        DueDate: { value: '04/03/2021' },
    },
    {
        id: { value: '5' },
        description: { value: 'Gpay' },
        DueDate: { value: '04/03/2020' },
    },
];

const descriptionSortedArray = rows.reduce((acc, current) => {
    acc[current.description.value] = [...(acc[current.description.value] || []), current];
    return acc;
}, {});

console.log(descriptionSortedArray);

const sortRowsByDate = (rows) =>
    rows.sort((a, b) => new Date(b.DueDate.value) - new Date(a.DueDate.value));

const transformedRows = Object.keys(descriptionSortedArray).reduce((acc, current) => {
    acc[current] = sortRowsByDate(descriptionSortedArray[current]);
    return acc;
}, {});

return (
    <div>
        <table>
            <thead>
                <tr>
                    <th>id</th>
                    <th>description</th>
                    <th>duedate</th>
                    <th></th>
                </tr>
            </thead>
            {Object.keys(transformedRows).map((rowKey) => {
                // console.log("rowKey===", rowKey)
                //   console.log(transformedRows[rowKey])
                console.log(rowKey);
                return (
                    <tbody key={rowKey}>
                        {transformedRows[rowKey].length > 1 ? (
                            <tr>
                                <td colSpan="4">
                                    <Accordion label={rowKey}>
                                        {transformedRows[rowKey].map((obj) => (
                                            <div key={obj.id.value}>
                                                <span>{obj.id.value}</span>
                                                <span>{obj.description.value}</span>
                                                <span>{obj.DueDate.value}</span>
                                                <span>{<button>-</button>}</span>
                                            </div>
                                        ))}
                                    </Accordion>
                                </td>
                            </tr>
                        ) : (
                            transformedRows[rowKey].map((obj) => (
                                <tr key={obj.id.value}>
                                    <td>{obj.id.value}</td>
                                    <td>{obj.description.value}</td>
                                    <td>{obj.DueDate.value}</td>
                                    <td></td>
                                </tr>
                            ))
                        )}
                    </tbody>
                );
            })}
        </table>
    </div>
);

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744357413a4570300.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信