Home > Mobile >  Dropdown doesn't work in a loop but normal
Dropdown doesn't work in a loop but normal

Time:10-07

I am making a dropdown accordion. After adapting my code to the example bellow, everything works fine:

Example: https://codepen.io/CreativeBulma/pen/YbQqoQ

trainingData

[{
    "von": "17:00",
    "bis": "18:00",
    "tag": "Mittwoch",
    "trainingsid": 46
},
{
    "von": "19:00",
    "bis": "21:00",
    "tag": "Donnerstag",
    "trainingsid": 51
}]

That's how it works:

 <div ref={collapsiblesRef} id={`accordion_first2`}>
                        
                            <div className="card">
                                <header className="card-header">
                                    <p className="card-header-title">
                                        montaj
                                    </p>
                                    <a href={`#collapsible-card-0`} data-action="collapse" className="card-header-icon is-hidden-fullscreen" aria-label="more options">
                                        <span className="icon">
                                            <i className="fas fa-angle-down" aria-hidden="true"></i>
                                        </span>
                                    </a>
                                </header>
                                <div id={`collapsible-card-0`} className="is-collapsible" data-parent={`accordion_first2`}>
                                    <div className="card-content">
                                        <p className="is-small has-text-primary has-text-weight-semibold">Tag</p>

                                        <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Wochentag" />
                                        <p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit von</p>
                                        <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit von" />

                                        <p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit bis</p>
                                        <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit bis" />

                                        <article className="message mt-3">
                                            <div className="message-body">
                                                Uhrzeit von ist die Startzeit und Uhrzeit bis ist die Endzeit des Trainings. Gültiges Format hh:mm, z.B. 17:45.
                                            </div>
                                        </article>


                                    </div>
                                </div>
                            </div>

                            <div className="card">
                                <header className="card-header">
                                    <p className="card-header-title">
                                        dasdasd
                                    </p>
                                    <a href={`#collapsible-card-1`} data-action="collapse" className="card-header-icon is-hidden-fullscreen" aria-label="more options">
                                        <span className="icon">
                                            <i className="fas fa-angle-down" aria-hidden="true"></i>
                                        </span>
                                    </a>
                                </header>
                                <div id={`collapsible-card-1`} className="is-collapsible" data-parent={`accordion_first2`}>
                                    <div className="card-content">
                                        <p className="is-small has-text-primary has-text-weight-semibold">Tag</p>

                                        <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Wochentag" />
                                        <p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit von</p>
                                        <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit von" />

                                        <p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit bis</p>
                                        <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit bis" />

                                        <article className="message mt-3">
                                            <div className="message-body">
                                                Uhrzeit von ist die Startzeit und Uhrzeit bis ist die Endzeit des Trainings. Gültiges Format hh:mm, z.B. 17:45.
                                            </div>
                                        </article>


                                    </div>
                                </div>
                            </div>

                    </div>

Since I am having several elements I want to add to the dropdown, I am using a loop. But unfortunately, after adding the loop, the collapsibles aren't working properly - they are staying open and I cannot close them or interact with them.

So that's actually what I want:

                <div ref={collapsiblesRef} id={`accordion_first`}>
                    {trainingData.map((d, i) => (
                        <div className="card" key={i}>
                            <header className="card-header">
                                <p className="card-header-title">
                                    {d.tag}
                                </p>
                                <a href={`#collapsible-card-${i}`} data-action="collapse" className="card-header-icon is-hidden-fullscreen" aria-label="more options">
                                    <span className="icon">
                                        <i className="fas fa-angle-down" aria-hidden="true"></i>
                                    </span>
                                </a>
                            </header>
                            <div id={`collapsible-card-${i}`} className="is-collapsible" data-parent={`accordion_first`}>
                                <div className="card-content">
                                    <p className="is-small has-text-primary has-text-weight-semibold">Tag</p>

                                        </div>*/}
                                    <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Wochentag" />
                                    <p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit von</p>
                                    <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit von" />

                                    <p className="is-small has-text-primary has-text-weight-semibold">Uhrzeit bis</p>
                                    <input className="input mb-5" style={{ width: "33%" }} type="text" placeholder="Uhrzeit bis" />

                                    <article className="message mt-3">
                                        <div className="message-body">
                                            Uhrzeit von ist die Startzeit und Uhrzeit bis ist die Endzeit des Trainings. Gültiges Format hh:mm, z.B. 17:45.
                                        </div>
                                    </article>


                                </div>
                            </div>
                        </div>


                    ))}

                </div>

CodePudding user response:

I played a bit with the code, this works for me.

import React from "react";
import bulmaCollapsible from '@creativebulma/bulma-collapsible';
import 'bulma';
import '@creativebulma/bulma-collapsible';


///I want to generate a random number of collapsibles.
const array = [0,1,2,3,4,5,6]

class Collapsibles extends React.Component {
  componentDidMount() {
    this.collapsibles = bulmaCollapsible.attach(".is-collapsible", {
      container: this.refs.collapsibles
    });
  }

  

  render() {

    const collapsibles = array.map((c,i) => <article className="message">
    <div className="message-header">
      <p>
        Question 1{" "}
        <a href={"#collapsible-message-accordion-"  i.toString()} data-action="collapse">
          Collapse/Expand
        </a>
      </p>
    </div>
    <div
      id={"collapsible-message-accordion-"  i.toString()}
      className="message-body is-collapsible is-active"
      data-parent="accordion_first"
    >
      <div className="message-body-content">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
        <strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
        porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
        Nullam gravida purus diam, et dictum
        <a>felis venenatis</a> efficitur. Aenean ac{" "}
        <em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
        sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
        magna a neque. Donec dui urna, vehicula et sem eget, facilisis
        sodales sem.
      </div>
    </div>
  </article>)
    return (
      <div ref="collapsibles" id="accordion_first">
        
        {collapsibles}
      </div>
    )
  }
}

export default Collapsibles

A few notes on the code:

  1. First, I assume you're aware that bulmaCollapsible is an npm package that needs to be installed. You can find directions for installation here.

  2. I didn't fully understand where you got your code from, I copied mine from the CodePen you provided. Each collapsible container is an article tag.

  3. My code lacks any transition properties. So it won't slowly open and close. You'll have to add some minor css to make that happen.

  4. The method attach is responsible to initialise any element with the className of is-collapsible. It was made so you can initialise multiple collapsibles at once.

  5. In my code I created an array const called "array". Then I used the map method like you did to generate multiple collapsibles.

  6. The following will give you 1 collapsible:

     <article className="message">
     <div className="message-header">
       <p>
         Question 1{" "}
         <a href={"#collapsible-message-accordion-"  i.toString()} data-action="collapse">
           Collapse/Expand
         </a>
       </p>
     </div>
     <div
       id={"collapsible-message-accordion-"  i.toString()}
       className="message-body is-collapsible is-active"
       data-parent="accordion_first"
     >
       <div className="message-body-content">
         Lorem ipsum dolor sit amet, consectetur adipiscing elit.{" "}
         <strong>Pellentesque risus mi</strong>, tempus quis placerat ut,
         porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla.
         Nullam gravida purus diam, et dictum
         <a>felis venenatis</a> efficitur. Aenean ac{" "}
         <em>eleifend lacus</em>, in mollis lectus. Donec sodales, arcu et
         sollicitudin porttitor, tortor urna tempor ligula, id porttitor mi
         magna a neque. Donec dui urna, vehicula et sem eget, facilisis
         sodales sem.
       </div>
     </div>
    
  7. Each collapsible needs to have a unique id. For each collapsible we use an a tag with an href attribute equal to the collapsible's id. This is reflected in the lines where you see href={"#collapsible-message-accordion-" i.toString()} and id={"#collapsible-message-accordion-" i.toString()}

To know more about how this package work, visit their JS API page.

  • Related