How can I create simple accordion with Angular 2?

回眸只為那壹抹淺笑 提交于 2019-12-11 01:55:15

问题


Before, I use this simple script to create a simple accordion

(function() { 

    $('dl.accordion').on('click', 'dt', function() {
        this_= $(this);
        this_
            .addClass("selected")
            .next()
                .slideDown(200)
                .siblings('dd')
                    .slideUp(200);
        this_.siblings()
            .removeClass("selected")

    });
})();

And this html

<dl class="accordion">
    <dt>What are your hours?</dt>
    <dd>We are open 24/7.</dd>
    <dt>What are your hours?</dt>
    <dd>We are open 24/7.</dd>
</dl>

Now I want to create a copy of this code written in Angular 2.

How can I create a simple acordion like above in Angular 2?

I guess I have to learn renderer, elementRef etc. Could you suggest other topics which I should learn to create this?


回答1:


try this solution, this is very simple accordion:

app/accordion.component.ts

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'tp-accordion',
  template: `
    <h2 class="accordion-head" (click)="onClick($event)">{{ title }}</h2>
    <div class="accordion-body" [class.active]="active">
      <ng-content></ng-content>
    </div>
  `,
  styles: [
    `
    .accordion-head {
      cursor: pointer;
    }
    .accordion-body {
      display: none;
    }
    .accordion-body.active {
      display: block;
      -webkit-animation: fadeIn .3s;
      animation: fadeIn .3s;
    }
    @-webkit-keyframes fadeIn {
      from { opacity: 0; transform: scale(0); }
        to { opacity: 1; transform: scale(1); }
    }  
    @keyframes fadeIn {
      from { opacity: 0; transform: scale(0); }
        to { opacity: 1; transform: scale(1); }
    }
    `  
  ],
})
export class Accordion {

  @Input() title: string;

  @Input() active: boolean = false;

  @Output() toggleAccordion: EventEmitter<boolean> = new EventEmitter();

  constructor() {}

  onClick(event) {
    event.preventDefault();
    this.toggleAccordion.emit(this.active);
  }

}

app/accordion-group.component.ts

import { Component, ContentChildren, QueryList, AfterContentInit, OnDestroy } from '@angular/core';

import { Accordion } from './accordion.component';

@Component({
  selector: 'tp-accordion-group',
  template: `
    <ng-content></ng-content>
  `
})
export class AccordionGroup {

  @ContentChildren(Accordion) accordions: QueryList<Accordion>;
  private subscriptions = [];

  private _accordions = [];

  constructor() {}

  ngAfterContentInit() {

    this._accordions = this.accordions;
    this.removeSubscriptions();
    this.addSubscriptions();

    this.accordions.changes.subscribe(rex => {
      this._accordions = rex;
      this.removeSubscriptions();
      this.addSubscriptions();
    });
  }

  addSubscriptions() {
    this._accordions.forEach(a => {
      let subscription = a.toggleAccordion.subscribe(e => {
        this.toogleAccordion(a);
      });
      this.subscriptions.push(subscription);
    });
  }

  removeSubscriptions() {
    this.subscriptions.forEach(sub => {
      sub.unsubscribe();
    });
  }

  toogleAccordion(accordion) {
    if (!accordion.active) {
      this.accordions.forEach(a => a.active = false);
    }
    // set active accordion
    accordion.active = !accordion.active;
  }

  ngOnDestroy() {
    this.removeSubscriptions();
  }

}

app/app.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { PostsService } from './posts.service';


@Component({
  selector: 'app-root',
  template: `
    <tp-accordion-group>
      <tp-accordion *ngFor="let post of posts" [title]="post.title">
        {{ post.body }}
      </tp-accordion>
    </tp-accordion-group>
  `
})
export class AppComponent implements OnInit, OnDestroy {

  posts = [];
  private subscription: any;

  constructor(private postsSvc: PostsService) {}

  ngOnInit() {
    this.subscription = this.postsSvc.getPosts().subscribe(res => {
      if (res.length) {
        this.posts = res.slice(0, 10);
      }
    })
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }

}

app/posts.service.ts

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class PostsService {
  postsUrl: 'https://jsonplaceholder.typicode.com/posts';
  constructor(private http: Http) {

  }
  getPosts() {
    return this.http.get(this.postsUrl)
      .map(res => {
        let body = res.json();
        return body || [];
      })
      .catch(console.log);
  }
}

Online demo: https://plnkr.co/edit/xFBllK?p=preview

Document:

  • EventEmitter
  • @ContentChildren
  • QueryList



回答2:


The Problem

The biggest thing to take away is knowing the "GetElementbyClassName" or "GetElementbyID" will not work unless it is being called within Angular 2. This is because the DOM will always load before Angular components loads thus there will never be an object to get a class or id from.

Solution

Angular has "Hooks" that you can tap into that will allow you to run code when a specific event happens, such as when component loads ngAfterViewInit()

This can all be avoided by using directives to do your accordion but if you want to run your above javascript, then just run that in an ngAfterViewInit() function in your export class componentName {}and it will work.

Sample

Here is a sample where I did exactly what I stated above:

import { Component } from '@angular/core';

@Component({
  selector: 'events',
  templateUrl: "partials/events.html"
})
export class EventsComponent {
    ngAfterViewInit() {
        var acc = document.getElementsByClassName("accordion");
        var i;

for (i = 0; i < acc.length; i++) {
    acc[i].onclick = function(){
        this.classList.toggle("active");
        this.nextElementSibling.classList.toggle("show");
        }
    }
}

} // export class



回答3:


I don't know whether my solution is legal within angular, but I've come up with a simple accordion using a service.

Click here to check out solution on stackblitz



来源:https://stackoverflow.com/questions/42113446/how-can-i-create-simple-accordion-with-angular-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!