Senny Kalidien
Senny Kalidien

Reputation: 65

Angular 2 - Accordion toggle class must close previous accordion

I'm building an accordion in Angular 2 and I what I want to accomplish is when I click on one of the accordions, the accordion will open and all other opened accordions will be closed (so basically the previously opened accordion will be closed). Without DOM manipulation.

How I'm doing this now now: I have a type boolean named 'classActive' which I toggle on true or false on click.

(note: the accordion is being looped by using ngFor)

HTML

<div class="accordion" [ngClass]="{'is-active' : classActive}">
    <div class="accordion__container">
        <div class="accordion__header" (click)="toggleClass($event)">
            <h2 class="accordion__heading">{{ name }}</h2>
        </div>
        <div class="accordion__content">
            {{ content }}
        </div>
    </div>
</div>

JS

@Component({
    selector: 'accordion',
    templateUrl: './accordion.component.html',
    styleUrls: ['./accordion.component.scss']
})
export class AccordionComponent implements OnInit {
    classActive: boolean = false;

    toggleClass(event) {
        event.preventDefault();
        this.classActive = !this.classActive;
    }
}

SCSS

.accordion {
    height: 100px;
    overflow: hidden;
    transition: height .3s cubic-bezier(1, 0, .41, 1.01);

    &.is-active {
        height: 200px;

        .accordion__content {
            opacity: 1;
        }
    }

    &__header {
        cursor: pointer;
        height: 100px;
        padding: 0 $p-container;
        position: relative;
    }

    &__heading {
        text-transform: lowercase;
        line-height: 100px;
        pointer-events: none;
    }

    &__content {
        opacity: 0;
        transition: opacity .6s;
        padding: $p-container;
    }
}

I think the solution would be to set all 'classActive' on false and then set the clicked one on true. But is that possible?

Upvotes: 1

Views: 4734

Answers (2)

Pooja V Raut
Pooja V Raut

Reputation: 5

[ngClass]="{'is-active' : activeIndex === i, 'is-dactive' : activeIndex != i}">

togglePopover(event, i: number) {
    event.preventDefault();
    this.activeIndex = i
    console.log(this.activeIndex);
  }

Upvotes: 0

developer033
developer033

Reputation: 24894

The problem, as mentioned in comments, is that you've created a single variable to handle multiple elements.

The simplest solution IMHO is to modify your function to "save" the current index clicked as below:

Component:

activeIndex: number = 0; // The accordion at index 0 will be open by default

toggleClass(i: number): void {
  this.activeIndex = i;
}

So, in your template you can just modify your [ngClass] to:

[ngClass]="{'is-active': activeIndex === i}"

Template:

<div *ngFor="let yourVariable of yourArray, let i = index">
  <div class="accordion" [ngClass]="{'is-active': activeIndex === i}">
    <div class="mood__container">
      <div class="mood__header" (click)="toggleClass(i)">
        <h2 class="mood__heading">{{ name }}</h2>
      </div>
      <div class="accordion__container>
        {{ content }}
      </div>
    </div>
  </div>
</div>

Check the complete code below:

DEMO

Upvotes: 1

Related Questions