2017-02-08 5 views
0

Раньше я использовать этот простой скрипт для создания простого аккордеонаКак создать простой аккордеон с угловым 2?

(function() { 

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

    }); 
})(); 

И этого 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> 

Теперь я хочу, чтобы создать копию этого кода, написанный на Угловом 2.

Как я могу создать простой аккордеон, как указано выше в Angular 2?

Я думаю, мне нужно изучить renderer, elementRef и т. Д. Не могли бы вы предложить другие темы, которые я должен научиться создавать?

ответ

2

попробовать это решение, это очень простой аккордеон:

приложение/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); 
    } 

} 

приложение/аккордеон-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.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(); 
    } 
    } 

} 

приложение/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); 
    } 
} 

Интернет демо: https://plnkr.co/edit/xFBllK?p=preview

Документ:

+0

Здравствуйте @Tiep, спасибо за ответ. Я пытаюсь использовать его. Я хочу задать вам еще один вопрос: «Что, если мой контент поступает из запроса ajax? Думаю, мне нужно запустить компонент группы аккордеона после загрузки запроса ajax. Но теперь он работает над ngAfterContentInit. Или мне нужно создать сервис? – Sam

+0

просто разместите свой контент внутри ' ... content ...' –

+0

Если вы имеете в виду динамический контент, я попробовал, он не работает. Метод toogleAccordion не запускается, когда я нажимаю аккордеон, если я загружаю контент через json с помощью * ngFor. – Sam

0

Проблема

Самое главное, чтобы забрать это знание «GetElementbyClassName» или «GetElementbyID» не будет работать, если это не вызывается в угловых 2. Это происходит потому, что DOM будет всегда загружайте до того, как будут загружены компоненты с угловыми компонентами, поэтому никогда не будет объекта для получения класса или идентификатора.

Решение

Угловая есть «зацепки», которые вы можете нажать на который позволит вам запускать код, когда происходит определенное событие, например, при загрузке компонента ngAfterViewInit()

Все это можно избежать с помощью директивы чтобы сделать свой аккордеон, но если вы хотите запустить свой выше JavaScript, то просто запустите его в функции в вашем export class componentName {}, и он будет работать.

Образец

Вот пример, где я сделал именно то, что я говорил выше:

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 
+0

onclick дает ошибку при компиляции. – Sam

Смежные вопросы