简体   繁体   中英

Cannot read property of undefined angular2

I have a problem when I want to use a method of an angular2 component. Here's the code :

import { Component,OnInit } from '@angular/core';
import { Router } from '@angular/router';
import {AgGridModule} from 'ag-grid-angular/main';
import {GridOptions, GridApi, ColumnApi} from "ag-grid";

import { AllService } from './all.service';
import { SomeClass } from './someClass';
import { ResponseData, Links } from './response';

import 'rxjs/Rx';

@Component({
  selector: 'all',
  styleUrls: ['./all.scss'],
  templateUrl: './all.html'
})

export class AllComponent implements OnInit {

embedded: Array<SomeClass>
page: number;
page_count: number;
link: Array<Links> = [];
total_items: number;
page_size: number;
private gridOptions: GridOptions = {
    enableFilter: true,
    enableSorting: true,
    //pagination: true,
    enableColResize: true,
    animateRows: true
};
private api: GridApi;
private columnApi: ColumnApi;
private json : JSON;
private test : String;
private n : number = 0;

constructor (private service: AllService, private router: Router) {

}

ngOnInit(){
    this.getData();
}

private myRowClickedHandler(event) {
    this.goToDetail(event.data.uuid);
}

private getData(){
  this.service.getInitData().subscribe(data => {  this.embedded = data._embedded.some_class;
                                                    this.page = data.page;
                                                    this.page_count = data.page_count;
                                                    this.page_size = data.page_size;
                                                    this.total_items = data.total_items;
                                                    this.link[0] = data._links;
                                                    this.createGrid();

                                                    this.gridOptions.api.addEventListener('rowClicked', this.myRowClickedHandler);
                                                });
}

private createGrid(){
    this.n = this.embedded.length;
    this.gridOptions.columnApi.autoSizeColumns;
    this.gridOptions.api.setColumnDefs(this.createColumnDefs());
    this.gridOptions.api.setRowData(this.createRows());
    this.gridOptions.api.sizeColumnsToFit();
}

private createRows(){

    var rowData:any[] = [];

    var regexp1 = /[a-zA-Z0-9]*$/;

    for (var i = 0; i < this.n; i++) {

        rowData.push({
            uuid: this.embedded[i].uuid,
            state: this.embedded[i].state,
            executionDate: this.embedded[i].executionDate,
            startDate: this.embedded[i].startDate,
            endDate: this.embedded[i].endDate,
            taskClass: regexp1.exec(this.embedded[i].taskClass)[0],
            humanDuration: this.embedded[i].humanDuration,
            humanMemoryConsumption: this.embedded[i].humanMemoryConsumption,
        });
    }

    return rowData;

}

private createColumnDefs() {
    return [
      {headerName: 'uuid', field: 'uuid'},
      {headerName: 'state', field: 'state', filter: 'text', cellStyle: function(params) {
          switch(params.value){
              case "STATE1": return {color: 'orange'};
              case "STATE23": return {color: 'green'};
              case "STATE8": return {color: 'red'};
          }
      }},
      {headerName: 'executionDate', field: 'executionDate'},
      {headerName: 'startDate', field: 'startDate'},
      {headerName: 'endDate', field: 'endDate'},
      {headerName: 'taskClass', field: 'taskClass'},
      {headerName: 'humanDuration', field: 'humanDuration'},
      {headerName: 'humanMemoryConsumption', field: 'humanMemoryConsumption'},
      {headerName: 'action', field: 'action'}
    ]
}

public goToDetail(uuid: String) {
    let link = ['pages/all', uuid];
    this.router.navigate(link);
}
 }

And here is the error I get :

EXCEPTION: Cannot read property 'goToDetail' of undefined

I don't really understand what is happening here... Is this due to the call from the subscribe method ?

Have you tried using the Function.prototype.bind() method, which lets you specify the value that should be used as this when the callback is triggered?

Like this:

this.gridOptions.api.addEventListener('rowClicked', this.myRowClickedHandler.bind(this), false);

If you do not specify which value should be used as this , the value of this inside the handler is a reference to the element (and, hence, undefined ).

What is happening here is that when your rowClicked event is triggered, this in this.goToDetail(event.data.uuid); is not executed from the call-site you might think it's executed from. They way you wrote it, you might think that it's call-site is AllComponent class, but it's really not, it's wherever your event listener is called from, and in execution time, this does not refer to your class.

Tobold's answer is one solution, but you can try it out with 'fat arrow' as well:

private myRowClickedHandler = (event) => {
    this.goToDetail(event.data.uuid);
}

Here, your myRowClickedHandler function will always have correct 'this'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM