0

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>


3 Answers3

0

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>
Dharman
  • 30,962
  • 25
  • 85
  • 135
T. Sunil Rao
  • 1,167
  • 5
  • 14
0

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!');
}
Rick
  • 1,710
  • 8
  • 17
0

You could define a helper Method in GudangComponent

getListCallback() {
  return this.getList.bind(this);
}

and use it here

<ngx-table-custom [callback]="getListCallback()" [columns]="column" [items]="tableData">
Lukasz Gawrys
  • 1,234
  • 2
  • 8