Cannot read property of undefined when calling method as a callback

I’m new to OOP and angular.
currently, I want to use reusable table with pagination that makes a request API if page change (pagination inside table component).

the problem is when I access my method using callback from table component (Child) I got undefined.

but when I try to move pagination to MasterGudang (Parent) Components it’s work.

I don’t really understand what’s going on.
Error undefined
enter image description here

but here some code.

table.component.ts

import { Subject } from 'rxjs';

@Component({
  selector: 'ngx-table-custom',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.scss']
})
export class TableComponent implements OnInit {

  constructor() { }

  @Input() items: any;
  @Input() callback: any;
  @Input() columns: [];
  p: number = 1;

  @ContentChild('action', { static: false }) actionRef: TemplateRef<any>;
  ngOnInit(): void {
    this.items = new Subject();
    this.items.next();
  }

  onChangePage = (evt) => {
    this.callback()
  }

Gudang.component.ts

import { MasterGudangService } from '../../../../@core/services/master-service/menu-gudang/gudang/masterGudang.service';

@Component({
  selector: "ngx-gudang",
  templateUrl: './gudang.component.html',
  styleUrls: ['./gudang.component.scss'],
})

@Injectable({
  providedIn: 'root'
})
export class GudangComponent implements OnInit {

  constructor(
    public masterGudangService: MasterGudangService
    ) {
      console.log(masterGudangService)
    }

  tableData: [];
  isEdit: boolean = false;

  currentPage: number = 1;

  ngOnInit(): void {
    this.getList();
  }

  getList (page?: number) {
    this.masterGudangService.getPgb(page? page: this.currentPage).subscribe(response => {
      const { data: { content, totalElements, size, number } } = response;
      this.tableData = Object.assign({
        data: content,
        total: totalElements,
        size: size,
        number: number
      });
    });
  }
}

And here I passing my function which is getList to table component

gudang.component.html

 <ngx-table-custom [callback]="getList" [columns]="column" [items]="tableData">
      <ng-template let-item #action>
        <div class="row">
          <button nbButton status="success" (click)="open(dialog, item, true)" class="mx-2" size="tiny"><nb-icon icon="edit"></nb-icon></button>
          <button nbButton status="danger" (click)="onDelete(item)" size="tiny"><nb-icon icon="trash"></nb-icon></button>
        </div>
      </ng-template>
    </ngx-table-custom>

MasterGudangService.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class MasterGudangService {

  constructor(private http: HttpClient) { }

  getPgb (page: number = 1, perPage: number = 10) :any {
    return this.http.get(`my-api-url/pgb?page=${page}&size=${perPage}`)
  }
}

table.component.html

<div class="row">
  <div class="col-12">
    <table class="table table-md table-striped">
      <thead>
      <tr style="background-color: #3366ff; color: #fff;">
        <th *ngFor="let column of columns" class="text-basic">{{ column.value }}</th>
      </tr>
      </thead>
      <tbody>
      <tr *ngFor="let item of items.data | paginate: { itemsPerPage: 10, currentPage: p, totalItems: items.total }; index as idx;">
        <td *ngFor="let column of columns">
          <div *ngIf="column.key === 'number';"><b class="text-basic">{{ idx + 1 }}</b></div>
          <div *ngIf="column.key !== 'action' && !isNested(column.key);" class="text-basic">{{ item[column.key] }}</div>
          <div *ngIf="isNested(column.key);" class="text-basic">{{ getKeys(item, column.key) }}</div>
          <!-- <div *ngIf="column.key === 'action; action_container"></div> -->
            <ng-template [ngIf]="column.key === 'action'" #action_content>
              <ng-container
              *ngIf="actionRef"
              [ngTemplateOutlet]="actionRef"
              [ngTemplateOutletContext]="{$implicit:item}">
            </ng-container>
          </ng-template>
        </td>
      </tr>
      </tbody>
    </table>
  </div>
</div>

<div class="row">
  <div class="col-12" align="center">
    <pagination-controls (pageChange)="onChangePage($event)"></pagination-controls>
  </div>
</div>


6 thoughts on “Cannot read property of undefined when calling method as a callback”

  1. The context of Gudang.component.ts will not be available using callback from table component.

    The proper way to implement should be passing the event instead of passing function for callback

    table.component.ts

    @Output() pageChange = new EventEmitter()
    onChangePage = (evt) => {
       this.pageChange.emit(evt);
    }
    

    gudang.component.html

    <ngx-table-custom (pageChange)="getList($event)" [columns]="column" [items]="tableData">
        ...
    </ngx-table-custom>
    
    Reply
  2. based on the error, it seems like masterGudangService is null at the time you are trying to access it. Adding this code might help you eliminate the error and at least debug what is going on and get a step further.

    ngOnInit(): void {
      if(this.masterGudangService)
        this.getList();
      else
        console.log('service not defined!');
    }
    
    Reply

Leave a Comment