Búsqueda de sitios web

typescript - El objeto es indefinido en la devolución de llamada del listener de eventos pasada como un método en Angular 2


Soy nuevo en Angular 2 y TypeScript, en mi proyecto he creado tablas dinámicamente y las he agregado al DIV del tablero. He asignado addEventListener a la tabla y estoy pasando un callback como método. Pero cada vez que se dispara un evento, el objeto (this.diamondSet en el código a continuación) aparece como indefinido. No pude encontrar qué hice mal

Por favor ayúdame a encontrar el error, gracias de antemano,

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>

Respuesta #1

cuando agregas el eventListener con .addEventListener(), el contexto this es el propio Elemento, no tu componente.

Puedes arreglar esto fácilmente usando una función flecha:

clickHandler = (e) => {
    ... // your function code here
}

Respuesta #2

Otra forma es vincular la función que no es flecha con tu componente.

clickHandlerUnbinded(e)  {
   ... // your function code here
}

clickHandler = this.clickHandlerUnbinded.bind(this); // this -> is your component

document.getElementById("diamond_container").addEventListener("click", this.clickHandler);

Ahora tienes un clickHandler con su contexto de this ligado a tu componente.

Usar la función flecha es obviamente más elegante.