Reputation: 342
I am new to angular 2 and typescript, in my project I have created tables dynamically and appended to board DIV. I have given addEventLister to the table and passing callback as a method. But whenever an event is triggered the, but the object(this.diamondSet in below code) is giving undefined. I couldn't find what I did wrong
Please help me to find the error, Thanks in advance,
app.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
board_row: number = 8;
board_col: number = 8;
cellNum: number = 0;
cellCordinates: Object = {};
diamond_count: number = 8;
diamondSet: Object = {};
winCount: number = 0;
ngOnInit() {
this.randomGenerators();
this.initializeBoard();
}
initializeBoard() {
let table = document.createElement("table");
table.id = "diamond_container";
for (let i = 0; i < this.board_row; i++) {
let tr = document.createElement('tr');
for (let j = 0; j < this.board_col; j++) {
let td = document.createElement('td');
this.cellCordinates[this.cellNum] = {
x: i,
y: j
};
td.className = "cell unknown";
td.id = `${this.cellNum}`;
this.cellNum++;
tr.appendChild(td);
}
table.appendChild(tr);
}
document.getElementById("board").appendChild(table);
document.getElementById("diamond_container").addEventListener("click", this.clickHandler);
}
randomGenerators() {
while (Object.keys(this.diamondSet).length < this.diamond_count) {
let randomnumber = Math.ceil(Math.random() * 63)
this.diamondSet[randomnumber] = randomnumber;
}
}
clickHandler(e) {
console.log("handru");
if (Object.keys(this.diamondSet).length) {
if (e.target.nodeName == 'TD') {
this.winCount++;
console.log("before")
if (this.diamondSet[e.target.id]) {
e.target.className = "cell diamond disabled";
delete this.diamondSet[e.target.id];
} else {
var slope = this.hint(e.target.id);
$('td').removeClass('arrow');
e.target.className = "cell arrow disabled";
e.target.style["boxShadow"] = 'none';
e.target.style["transform"] = "rotate(" + slope + "deg)";
}
}
}
}
minDistance(clicked_id) {
var distanceMap = {};
Object.keys(this.diamondSet).map((id) => {
distanceMap[id] = Math.abs(this.cellCordinates[clicked_id].x - this.cellCordinates[id].x) + Math.abs(this.cellCordinates[clicked_id].y - this.cellCordinates[id].y);
});
return Object.keys(distanceMap).sort(function(a, b) {
return distanceMap[a] - distanceMap[b]
})[0];
}
hint(clicked_id) {
let nearestDiamondId = this.minDistance(clicked_id);
return (Math.atan2((this.cellCordinates[nearestDiamondId].x - this.cellCordinates[clicked_id].x), (this.cellCordinates[nearestDiamondId].y - this.cellCordinates[clicked_id].y))) * 180 / Math.PI;
}
}
app.component.html
<div class="container" id="container">
<center>
<h1>
Diamond Sweeper
</h1>
</center>
<div class="row">
<div class="col-xs-12" id="board">
</div>
</div>
</div>
Upvotes: 2
Views: 2125
Reputation: 857
Another way is to bind the non-arrow function with your component.
clickHandlerUnbinded(e) {
... // your function code here
}
clickHandler = this.clickHandlerUnbinded.bind(this); // this -> is your component
document.getElementById("diamond_container").addEventListener("click", this.clickHandler);
Now you got a clickHandler
with its this
context bound to your component.
Using arrow function is more elegant obviously.
Upvotes: 0
Reputation: 1698
when you add the eventListener with .addEventListener(), the this context is the Element itself, not your component.
You can fix this easily by using arrow function:
clickHandler = (e) => {
... // your function code here
}
Upvotes: 6