skip to Main Content

I have made a collapsible button with tokens inside using reactstrap and everything is working fine for button click collapse.

I would like to have this scenario as it is, but in the other hand how could I modify this to make all the collapsible buttons open on initial render of page.

While visiting the page, all the tokens needs to be visible means all the collapsible items needs to get opened.

If we give,

this.state = {
      open: [0 , 1, 2]
    };

then it will be opened but for this post it will work whereas in real applciation I don’t know what would be the exact index so hard coding like this won’t work.

Kindly help me to open all the n numbers of collapsible data to be opened on intial state and upon clicking the button it should be as like now (open/close) tokens.

const data = [{"orderId":1,"orderNo":"123", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1", "Token2","Token3"]}] },
{"orderId":2,"orderNo":"456", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1","Token3"]}] },
{"orderId":3,"orderNo":"789", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1", "Token2","Token3", "Token4"]}] }
]

const {Component, Fragment} = React;
const {Button, Collapse} = Reactstrap;

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      open: []
    };
  }
  
  toggle = idx => () => {
    this.setState(prevState => ({open: this.state.open.includes(idx) ? prevState.open.filter(x => x !== idx) : [...prevState.open, idx]})
  )}
  render() {
  const { open } = this.state;
    return <div> 
      {
        data.map((levelOneItem, i) => {
          return(
          <div>
          <div> Order Id:  {levelOneItem.orderId} </div>
          {
            levelOneItem.orderParts.map((levelTwoItem, j) => {
               return(
                  <div>
                  <div> Order Part Id: {levelTwoItem.orderPartsId} </div>
                  <Button onClick={this.toggle(i)}>Display Token</Button>
                  <Collapse isOpen={open.includes(i)}>
                    {
                       <div>
                        {levelTwoItem.regTokens.map((levelThreeItem, k) => {
                          return(<span> {levelThreeItem} </span>)
                        })
                     }
                       </div>
                    }
                  </Collapse>
                  </div>
               )
            })
          }
          </div>
          )
        })
      }
    </div>;
  }

}


ReactDOM.render(<Menu />, document.getElementById("root"));
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reactstrap/8.4.1/reactstrap.min.js"></script>

<div id="root"></div>

2

Answers


  1. If you want all of them been opened when init.

    Which means the index list of all the items

    You can generate a list like [0, 1, 2...] based on the length of data

    this.state = {
      open: [...Array(data.length).keys()]
    }
    
    const data = [{"orderId":1,"orderNo":"123", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1", "Token2","Token3"]}] },
    {"orderId":2,"orderNo":"456", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1","Token3"]}] },
    {"orderId":3,"orderNo":"789", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1", "Token2","Token3", "Token4"]}] }
    ]
    
    const {Component, Fragment} = React;
    const {Button, Collapse} = Reactstrap;
    
    class Menu extends Component {
      constructor(props) {
        super(props);
        this.state = {
          open: [...Array(data.length).keys()]
        };
      }
      
      toggle = idx => () => {
        this.setState(prevState => ({open: this.state.open.includes(idx) ? prevState.open.filter(x => x !== idx) : [...prevState.open, idx]})
      )}
      render() {
      const { open } = this.state;
        return <div> 
          {
            data.map((levelOneItem, i) => {
              return(
              <div>
              <div> Order Id:  {levelOneItem.orderId} </div>
              {
                levelOneItem.orderParts.map((levelTwoItem, j) => {
                   return(
                      <div>
                      <div> Order Part Id: {levelTwoItem.orderPartsId} </div>
                      <Button onClick={this.toggle(i)}>Display Token</Button>
                      <Collapse isOpen={open.includes(i)}>
                        {
                           <div>
                            {levelTwoItem.regTokens.map((levelThreeItem, k) => {
                              return(<span> {levelThreeItem} </span>)
                            })
                         }
                           </div>
                        }
                      </Collapse>
                      </div>
                   )
                })
              }
              </div>
              )
            })
          }
        </div>;
      }
    
    }
    
    
    ReactDOM.render(<Menu />, document.getElementById("root"));
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/reactstrap/8.4.1/reactstrap.min.js"></script>
    
    <div id="root"></div>
    Login or Signup to reply.
  2. It looks like reactstrap don’t support such things. But here is an workaround to that.

    const data = [{"orderId":1,"orderNo":"123", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1", "Token2","Token3"]}] },
    {"orderId":2,"orderNo":"456", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1","Token3"]}] },
    {"orderId":3,"orderNo":"789", "orderParts":[{"orderPartsId":1,"orderPrtNo":"OP-1", "regTokens":["Token1", "Token2","Token3", "Token4"]}] }
    ]
    
    const {Component, Fragment} = React;
    const {Button, Collapse} = Reactstrap;
    
    class Menu extends Component {
      constructor(props) {
        super(props);
        this.state = {
          open: [],
          isFirstTime:true
        };
      }
      
      toggle = idx => () => {
      if(this.state.isFirstTime){
      var ids=data.map(item=>item.orderId);
      
      //get all id of data here as ids;
     
      this.setState({
        isFirstTime:false,
        open:ids.filter(x=>x!==idx)
      });
      }else{
        this.setState(prevState => ({open: this.state.open.includes(idx) ? prevState.open.filter(x => x !== idx) : [...prevState.open, idx]})
      )
      }
      }
      render() {
      const { open } = this.state;
        return <div> 
          {
            data.map((levelOneItem, i) => {
              return(
              <div>
              <div> Order Id:  {levelOneItem.orderId} </div>
              {
                levelOneItem.orderParts.map((levelTwoItem, j) => {
                   return(
                      <div>
                      <div> Order Part Id: {levelTwoItem.orderPartsId} </div>
                      <Button onClick={this.toggle(levelOneItem.orderId)}>Display Token</Button>
                      <Collapse isOpen={open.includes(levelOneItem.orderId)||this.state.isFirstTime}>
                        {
                           <div>
                            {levelTwoItem.regTokens.map((levelThreeItem, k) => {
                              return(<span> {levelThreeItem} </span>)
                            })
                         }
                           </div>
                        }
                      </Collapse>
                      </div>
                   )
                })
              }
              </div>
              )
            })
          }
        </div>;
      }
    
    }
    
    
    ReactDOM.render(<Menu />, document.getElementById("root"));
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/reactstrap/8.4.1/reactstrap.min.js"></script>
    
    <div id="root"></div>

    Here isFirstTime indicates the initial state, so all collapse will get true, when any one of them changes, isFirstTime will be false, and rest will be done as is

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search