Reputation: 81
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 ?
Upvotes: 3
Views: 803
Reputation: 4324
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'.
Upvotes: 2
Reputation: 4074
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).
Upvotes: 3