1

I have a project based on the Angular.io tutorial, including "Hero"-interface and data, as well as a "HeroService" using HTTPClient.

I am able to fetch the data and display it using standard HTML in the template, but not when using the PrimeNG table, using the example from their webpage. So I have the data I need for the template, but I am not sure how to correctly pass it to PrimeNG. I am hoping to do it whithout changing how the HeroSerice works.

I am in general confused by Observables, Promises, and associated tech, so it's hard to describe further. I have read Using PrimeNG with Observables (rxjs) in Angular 4, without solving my issue.

Hero Interface:

export interface Hero {
  id: number;
  name: string;
}

InMemoryDataService:

export class InMemoryDataService implements InMemoryDbService {
  createDb() {
    const heroes = [
      { id: 11, name: 'Dr Nice' },
      { id: 12, name: 'Narco' },
      { id: 13, name: 'Bombasto' },
      { id: 14, name: 'Celeritas' },
      { id: 15, name: 'Magneta' },
      { id: 16, name: 'RubberMan' },
      { id: 17, name: 'Dynama' },
      { id: 18, name: 'Dr IQ' },
      { id: 19, name: 'Magma' },
      { id: 20, name: 'Tornado' }
    ];
    return {heroes};
  }

Method from HeroService:

  /** GET heroes from the server */
  getHeroes(): Observable<Hero[]> {
    return this.http.get<Hero[]>(this.heroesUrl)
      .pipe(
        catchError(this.handleError<Hero[]>('getHeroes', []))
      );
  }

My TreeTableComponent:(naming from before I scaled it down to be a table)

export class TreeTableComponent implements OnInit {

  heroes: Hero[] = [];
  

  constructor(private heroService : HeroService) { }

  ngOnInit() {
    this.getHeroes();
  }
  
  getHeroes(): void {
    this.heroService.getHeroes().pipe(tap(heros => console.log(heros)))
    .subscribe((heroes: Hero[]) => {
      this.heroes = heroes as Hero[];
    }
      )};

So, the issue:

This works:

  <ul class="heroes">
    <li *ngFor="let hero of heroes">
      <a routerLink="/detail/{{hero.id}}">
        <span class="badge">{{hero.id}}</span> {{hero.name}}
      </a>
    </li>
  </ul>

But this does not:

<p-table [value]="heroes"| async>
    <ng-template pTemplate="header">
        <tr>
            <th>id</th>
            <th>name</th>        
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-hero>
        <tr>
            <td>{{heroes.id}}</td>
            <td>{{heroes.name}}</td>
        </tr>
    </ng-template>
  </p-table>[enter image description here][1]

The error I get is:

TS2339: Property 'id' does not exist on type 'Hero[]'.

TS2339: Property 'name' does not exist on type 'Hero[]'.

![1]: https://i.stack.imgur.com/EJ06E.png

eulker
  • 13
  • 2

1 Answers1

2

You are using the wrong variable name.

<ng-template pTemplate="body" let-hero>

In the line above, you are naming the variable as "hero" to access individual elements of the "heroes" array. So, the properties should be called like this:

<td>{{hero.id}}</td>
sofa_maniac
  • 1,659
  • 2
  • 12
  • 21
  • 1
    That did it! However I think you forgot to change heroes to hero in your reply. I also had to remove "| Async" due to: 'Element '|' is not a valid attribute name. I thought that was mandatory when using observables? – eulker Apr 29 '21 at 15:14
  • Yes I missed that! – sofa_maniac Apr 29 '21 at 15:17