0

New to Angular therefore struggling to determine the root cause of this issue. I need to create a POC dashboard where the UI is built from data pulled from the client's sharepoint site - using the httpclient to call the SP rest api. Decided to use json-server as a provider while the SP was being finalised but I cannot seem to get the output required. Pretty sure it will be something really basic that I am unaware of.

//***dashboard.component.ts

import { Component, OnInit } from "@angular/core";
import { DashboardService } from "./dashboard.service";
import { StrategicItem  } from "../../model/StrategicItem";
import { Observable } from "rxjs/Observable";

@Component({
   selector: "app-dashboard",
   templateUrl: "./dashboard.component.html",
   styleUrls: ["./dashboard.component.css"], 
   providers: [DashboardService]
 })

export class DashboardComponent implements OnInit
 {
 private strategicItems: Observable<StrategicItem[]>;
 constructor(private dashboardService: DashboardService){}

 ngOnInit()
    {
    this.getStrategicItems();
    }

 getStrategicItems(): void
    {
    this.strategicItems = this.dashboardService.getStrategicItems();
    }
 }

//***dashboard.service.ts

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import {StrategicItem } from "../../model/StrategicItem";
import { Observable } from "rxjs/Observable";


@Injectable()
export class DashboardService {
    private readonly safeUrl: string = "http://localhost:8900/safe"; 

    constructor(private httpClient: HttpClient) {}

    getStrategicItems(): Observable<StrategicItem[]>
      {
      return this.httpClient.get<StrategicItem[]>(this.safeUrl);
      }
}

The issue is within the ngFor portion of layout where I want to iterate the list and populate the UI

//***dashboard.component.html

...
<mat-card>
   <mat-card-header class="slate">
      <mat-card-title>Leading Indicators</mat-card-title>
   </mat-card-header>
   <mat-list>
      <mat-list-item *ngFor="let item of strategicItems | async">
         <mat-icon>chevron_right</mat-icon><a href="">{{item.title}}</a>
      </mat-list-item>
   </mat-list>
</mat-card>
...

//***db.json

{
"safe": [
    { "title": "Work Safety Controls System" },
    { "title": "Incident Management" },
    { "title": "Safety Critical Element Performance" },
    { "title": "Management of Change" },
    { "title": "Emergency Preparedness" },
    { "title": "Safe Design Limit Excursion" },
    { "title": "Interlocks and Bypasses" }
]

}

Fiddler shows the json-server returning the data but this UI list remains empty.

Chrome debugger shows the following for the ngFor - few resources describing this exact error on google but I'm assuming the issues lies with my implementation around httpclient/async/binding.

enter image description here

I used https://codecraft.tv/courses/angular/http/http-with-observables/ as a reference/starter - been through line by line to see if I missed anything but don't know enough about Angular yet to pick up obvious indicators - just running out of time

2 Answers 2

3

The thing is that your JSON file returns with safe as some type that holds the collection of strategic items. You are not enumerating properly. I would make a slight change to the layout first. For example:

<ng-container *ngIf="strategicItem | async as strategicItems">
    <mat-list-item *ngFor="let item of strategicItems.safe">
        <mat-icon>chevron_right</mat-icon><a href="">{{item.title}}</a>
    </mat-list-item>
</ng-container

ng-container will not get rendered in a sense that it would affect your Material components. If you have a problem with ng-container at this point, try to move it further up the tree, probably by wrapping mat-card element with ng-container.

This should do the trick. Also, in order to follow the convention, you should name your observable variable as strategicItem$.

Sign up to request clarification or add additional context in comments.

Comments

1

Like Husein Roncevic mentionned, your problem is likely caused by your data being contained in "safe" property.

What you can do, if you want to be working directly with the good type after calling your service, is modify your getStrategicItems method like below to map the response's safe property to the correct StrategicItem[] type

getStrategicItems(): Observable<StrategicItem[]>
  {
      return this.httpClient.get(this.safeUrl).map ((resp : any) => resp.safe as StrategicItem[]);
  }

You can keep the rest of your code unchanged

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.