0

I have a backend database that serves student records as JSON files. These objects are then populated in a PrimeNG table for display and selection.

student.component.html

<p-table class="table" [columns]="cols" [value]="searchResults">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
       </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowData>
        <tr [pSelectableRow]="rowData" class="tr-click" (click)="getSelected(rowData)">
            <td *ngFor="let col of columns">
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-table>

However when I attempt to read or iterate through the student records in TypeScript, I get "TypeError: Cannot read property XXX of undefined".

student.component.ts

export class StudentComponent implements OnInit {

    searchResults: Student[];
    cols: any[];

    constructor(private router: Router, private studentService: StudentService, private http: HttpClient) {

    }

    ngOnInit(): void {
        this.studentService.getStudents().subscribe(data => {
            this.searchResults = data;
        });

        // table columns
        this.cols = [
            { field: 'studentId', header: 'Student ID'},
            { field: 'name', header: 'Name'},
            { field: 'dob', header: 'Date of Birth'},
            { field: 'status', header: 'Status'}
        ];

        // tested the object with these
        alert('1: ' + JSON.stringify(this.searchResults)); // undefined
        alert('2: ' + this.searchResults);                 // undefined
        alert('3: ' + this.searchResults.toString);        // undefined
    }

   // This is what I am trying to accomplish
   getSelected(selected: Student) {
       for (const result of this.searchResults) {
           if (selected.studentID === result.studentID) {
               // do some other stuff
       }
   }
}

So why is the PrimeNG table able to populate the table with the object, but I can't iterate over it in TypeScript? How do I get it to treat the object as an array?

sml485
  • 367
  • 1
  • 6
  • 19
  • 1
    Post the error message, with the property name showing. – R. Richards Jan 19 '19 at 13:04
  • alert('1: ' + JSON.stringify(this.searchResults)); is undefined because data may be not resolved yet. Remember that observable is async. – Patryk Błaziński Jan 19 '19 at 13:09
  • Please reduce this question down to the minimum needed to explain the problem, include error messages and provide a detail description of the question. Pasting your source code and asking why it doesn't work is off topic. – Reactgular Jan 19 '19 at 13:11

1 Answers1

1

apparently there is no columns declaration in your ts file

<tr [pSelectableRow]="rowData" class="tr-click" (click)="getSelected(rowData)">
    <td *ngFor="let col of columns">
        {{car[col.field]}}
    </td>
</tr>

to

<tr [pSelectableRow]="rowData" class="tr-click" (click)="getSelected(rowData)">
    <td *ngFor="let col of cols">
        {{car[col.field]}}
    </td>
</tr>

Edit: You are subscribing to an async method with subscribe, but you are trying to make assignments after subscription. because of this your function does not wait subscription to finish. The solution of your problem is :

this.studentService.getStudents().subscribe(data => {
    this.searchResults = data;

     // table columns
    this.cols = [
      { field: 'studentId', header: 'Student ID'},
      { field: 'name', header: 'Name'},
      { field: 'dob', header: 'Date of Birth'},
      { field: 'status', header: 'Status'}
    ];

    // tested the object with these
    alert('1: ' + JSON.stringify(this.searchResults)); // undefined
    alert('2: ' + this.searchResults);                 // undefined
    alert('3: ' + this.searchResults.toString);        // undefined
});
Derviş Kayımbaşıoğlu
  • 28,492
  • 4
  • 50
  • 72
  • Sorry, that was a typo when I was writing the question. – sml485 Jan 19 '19 at 13:37
  • So every method that works on the retrieved data (like my `for` loop) has to be called inside the subscribe function? To ensure they are only executed when the data is actually available? – sml485 Jan 19 '19 at 16:58
  • If you need to wait for the result, everything related with your work is needed to be called inside subscribe function. If this answer is helpfull for you please consider to upvote and/or mark it as answer. – Derviş Kayımbaşıoğlu Jan 19 '19 at 17:03
  • 1
    Thank you for the answer. I'm new to angular and the way subscribe and observables work has been throwing me for a loop. – sml485 Jan 20 '19 at 04:05