Aleksandar
Aleksandar

Reputation: 119

How to access element by id in angular 2

I have table generated with dynamic ids like this one

<table>
    <tbody>
        <tr *ngFor="let row of createRange(seats.theatreDimension.rowNum)">
            <td id={{row}}_{{seat}} *ngFor="let seat of createRange(seats.theatreDimension.seatNumInRow)">

            </td>
        </tr>
    </tbody>
</table>

I want to access table td element from angular 2 .ts file. Here are functions:

ngOnInit() {
    this.getSeats();
}

getSeats() {
    this.cinemaService.getAllSeats(this.repertoire.id).subscribe(
        data => {
            this.seats = data.json();   
            this.setReservedSeats();
        }
    )
}
setReservedSeats() {
    this.seats.reservedSeats.forEach(seat => {
            let cssSeatId = seat.rowNumReserved + "_" + seat.seatNumInRowResereved;
            document.getElementById(cssSeatId).className += "reserved";
        }
    )
}

and after that I want dynamically to set class of every td, but I am getting this console error in my browser:

ERROR TypeError: Cannot read property 'className' of null

Just to note once again that I generate td ids dynamically. They are in form rowNum_cellNum.

I am getting this object from api.

{
"theatreDimension": {
    "rowNum": 17,
    "seatNumInRow": 20
},
"reservedSeats": [
    {
        "rowNumReserved": 9,
        "seatNumInRowResereved": 19
    },
    {
        "rowNumReserved": 2,
        "seatNumInRowResereved": 4
    },
    {
        "rowNumReserved": 15,
        "seatNumInRowResereved": 15
    }
]

}

I am using theatreDimension to make table. Then I try to make reserved seats from reservedSeats array with red background (reserved)

How I can access td elements from angular 2 and solve this issue?

Upvotes: 0

Views: 1753

Answers (2)

user184994
user184994

Reputation: 18281

Instead of accessing the DOM directly, you should try using the ngClass directive to set the class:

<td [ngClass]="{'reserved': isReserved(row, seat)}" id={{row}}_{{seat}} *ngFor="let seat of createRange(seats.theatreDimension.seatNumInRow)">

</td>

You can then implement the isReserved(row, seat) function, and if it returns true, it will apply the reserved class.

isReserved(rowNum: number, seatNum: number) {
    return this.seats.reservedSeats.some((r) => r.rowNumReserved === rowNum && r.seatNumInRowResereved === seatNum);
}

Upvotes: 2

SKennick
SKennick

Reputation: 11

To directly answer your question, in order to get the element by ID, you need to do so after the page has been renedered. Use the function ngAfterViewInit(). You will need to remove the call to setReservedSeats() from getSeats().

ngOnInit() {
    this.getSeats();
}

ngAfterViewInit(){
    this.setReservedSeats();
}

However, I would suggest going a different route. You can set the style of the element based on whether or not the seat has been reserved. Assuming you have some sort of "reserved" flag on the seat object you can do something like this:

<td id={{row}}_{{seat}} 
    [ng-class]="{'reserved' : seat.researved}"
    *ngFor="let seat of createRange(seats.theatreDimension.seatNumInRow)">
</td>

Upvotes: 0

Related Questions