0

I am trying to run a script that will add classes to two divs, this will result in an accordion effect.

I am using a JSON file to load in the data and using NgFor to build the divs. The problem is that the DOM returns 'Null', when trying to use GetElementbyClassName().

If I remove the NgFor and use static text, this solution works just fine. Once I turn on NgFor I always get Null. This is all running inside ngAfterViewInit() so I don't understand why it can't at-least find the first div.accordion.

I don't have the strongest background in programming so if you could clearly explain what I need to do to resolve this issue I would be very appreciative

HTML

 <!--EVENTS-->
    <section class="eventssection">
        <div class="eventscontainer">
            <div class="eventsbody">
                <div class="eventsheader">Events</div>
                <div class="notice">Our Events and programs are made possible by our members and public donations</div>
                <div class="details">
                    <p>The Halifax Wildlife Association works hard to offer program and events to the public that help educate and generate awareness on issues that affect our wildlife and or access to.</p>
                </div>
                <div class="controllers">
                    <div id="expand" class="button">Expand All</div>
                    <div id="collapse" class="button">Collapse All</div>
                </div>
                <div class="accordioncontainer" *ngFor="let event of events">
                    <!--Button 1-->
                    <div class="accordion">{{ event.title }}</div>
                    <div class="panel">
                        <p>{{ event.description }}</p>
                    </div>
                </div> <!--end accordion container-->

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

Component

@Component({
  selector: 'events',
  templateUrl: "partials/events.html"
})
export class EventsComponent {
    events = [];

    constructor(private _eventsService: EventsService){}
    ngOnInit(){
        this._eventsService.getEvents()
        .subscribe(resEventsData => this.events = resEventsData);
    }   
    ngAfterViewInit() {
        //Declare Variables
        var accordion   = document.getElementsByClassName('accordion');
        var i           = 0;

        console.log(accordion); // tests getElementById

        for (i = 0; i < accordion.length; i++) {
            accordion[i].onclick = function(){
                this.classList.toggle("active");
                this.nextElementSibling.classList.toggle("show");
            } // click
        } //for loop 
    } // ngAfterView Init
} // export class
PhiLho
  • 40,535
  • 6
  • 96
  • 134
Bromox
  • 567
  • 2
  • 9
  • 29

2 Answers2

0

You can get a handle to the DOM element via ElementRef by injecting it into your component's constructor:

constructor(myElement: ElementRef) { ... }

Docs: https://angular.io/docs/ts/latest/api/core/index/ElementRef-class.html

May be this will help you:

  1. https://stackoverflow.com/a/38002785/2846450
  2. How to get dom element in angular 2
Community
  • 1
  • 1
Devansh
  • 1,277
  • 1
  • 13
  • 19
0

In current situation whats happening is ngFor haven't render its element and you're trying to get element from it. Though I will prefer you to go for template driven declarative approach. You don't need to bind event explicitly by looping through a DOM.

<div class="accordioncontainer" *ngFor="let event of events">
    <!--Button 1-->
    <div class="accordion" (click)="event.show = !event.show">{{ event.title }}</div>
    <div class="panel" [ngClass]="{'show': event.active}">
        <p>{{ event.description }}</p>
    </div>
</div> 
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299