Search code examples
angularhtml-tableangular-ng-ifuncaught-reference-error

Angular api response data not displaying in table


I am new to angular so following Deborah Kurata's angular getting started and reactive forms courses. In the course code there is a product-list component which in the template has a table and in the model calls a products service to retrieve some data in the ngOnInit.

I am using this as an example for my own application where I fetch categories from the backend and display them in a table in the same way.

The problem is that while the example code works and loads the data into the table, my code is not displaying any data in the table.

The getCategories method successfully gets 5 items from the back end. Why is this not visible to the template?

Template code

    <div class='table-responsive'>
          <table class='table mb-0'
           *ngIf='categories && categories.length'>
            <thead>
              <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Description</th>
                <th>Notes</th>
                <th>Actions</th>
              </tr>
            </thead>
            <tbody>
              <tr *ngFor="let category of filteredCategories">
                <td>
                  <a [routerLink]="['/category-list', category.id]">
                    {{ category.id }}
                  </a>
                </td>
                <td>{{ category.name }}</td>
                <td>{{ category.description }}</td>
                <td>{{ category.notes }}</td>
                <td>
                  <button class="btn btn-outline-primary btn-sm"
                    [routerLink]="['/categories', category.id, 'edit']">
                    Edit
                  </button>
                </td>
              </tr>
            </tbody>
          </table>
        </div>

Model code

    export class CategoryListComponent implements OnInit {
      pageTitle = 'Categories';
      errorMessage = '';
    
      sub!: Subscription;
    
      filteredCategories: Category[] = [];
      categories: Category[] = [];
    
      _listFilter = '';
      get listFilter(): string {
        return this._listFilter;
      }
      set listFilter(value: string) {
        this._listFilter = value;
        this.filteredCategories = this.listFilter ? this.performFilter(this.listFilter) : this.categories;
      }
    
      constructor(private categoryService: CategoryService) { }
    
      performFilter(filterBy: string): Category[] {
        filterBy = filterBy.toLocaleLowerCase();
        return this.categories.filter((category: Category) => 
        category.name.toLocaleLowerCase().indexOf(filterBy) !== -1);
      }
    
      ngOnInit(): void {
        this.sub = this.categoryService.getCategories().subscribe({
          next: c => {
            this.categories = c;
            this.filteredCategories = this.categories;
          },
          error: err => this.errorMessage = err
        });
      }
    }

Service code

  getCategories(): Observable<Category[]> {
    return this.httpClient.get<Category[]>(this.categoriesBaseUrl + "/GetAll")
      .pipe(
        tap(data => console.log(JSON.stringify(data))),
        catchError(this.handleError)
      )
  }

Edit: another difference is that the course uses the 'angular-in-memory-web-api' while I'm using an actual api. When debugging with breakpoints in the model ngOnInit categories can be seen in watch list populated with data, but by the time it gets into the template breakpoint on ngIf 'categories' in watchlist is 'undefined'


Solution

  • The issue was that the api was returning the categories array within an object as a property, and this couldn't be assigned directly to a variable of type Category[]. Changed the api to return the category array directly without the wrapper object and the data now displays in the table.