angulartypescriptangular-in-memory-web-api

Can't get angular-in-memory-web-api 0.6.1 to work following the tutorial


So I've followed the tutorial from https://angular.io/tutorial/toh-pt6 . I've tailored the tutorial to my specific case, which is just displaying a dashboard. When I use a local mock my code works perfectly fine. It's when I upgrade to the in memory web api that things go wrong.

The error that I'm recieving Error message

I've checked out the live code example (ref. https://stackblitz.com/angular/vvxldjlmnna) and can't really find the impacting code that I'm doing wrong.

First off I've installed the npm package using npm install angular-in-memory-web-api --save. I've checked the node_modules and see that this has indeed been downloaded succesfully, as was mentioned by the CLI. Checking the package.json file, i can see that in the dependencies "angular-in-memory-web-api": "^0.6.1", has been added

In the app.module.ts I've imported these modules in this specific order:

@NgModule({
    FormsModule, 
    HttpClientModule,
    HttpClientInMemoryWebApiModule.forRoot(InMemoryDataService), 
    // I also tried:
    // HttpClientInMemoryWebApiModule.forRoot(
    //     InMemoryDataService, { dataEncapsulation: false }
    // ),
    AppRoutingModule

I'm using the router-outlet to display the dashboard. To do this I'm using a router module with:

const routes: Routes = [{ path: 'dashboard', component: DashboardComponent },
                        { path: '', redirectTo: '/dashboard', pathMatch: 'full' }
];
@NgModule({
    imports: [ RouterModule.forRoot(routes) ],
    exports: [ RouterModule ]
})

In my in-memory-data.service.ts file

export class InMemoryDataService implements InMemoryDbService {
    createDb() {
        const DashboardReports = [
            { id: 1, date: new Date(2018, 8, 3, 0, 0, 0, 0), overtime: 0, project: 'W31226', superintendent: 'Toon', km: 105, status: 1 },
            { id: 2, date: new Date(2018, 8, 4, 0, 0, 0, 0), overtime: 1.75, project: 'W31226', superintendent: 'Toon', km: 105, status: 2 }
        ];

        return {DashboardReports}; // I paid specific attention to the curly braces here
    }
}

// Overrides the genId method to ensure that a hero always has an id.
// If the DashboardReports array is empty,
// the method below returns the initial number (21).
// if the DashboardReports array is not empty, the method below returns the highest
// report id + 1.
genId(dashboardreport: DashboardReport[]): number {
    return dashboardreport.length > 0 ? Math.max(...dashboardreport.map(report => report.id)) + 1 : 21;
}

In my dashboard.service.ts file, i inject HttpClient and call the dashboarddata from the api, having imported Observable from 'rxjs' and HttpClient from '@angular/common/http'. This is the DashboardService:

private dashboardDataUrl = 'api/dashboard';

constructor(private http: HttpClient) { }

/** GET Dashboard Reports from the server */
getDashboardReports (): Observable<DashboardReport[]> {
    return this.http.get<DashboardReport[]>(this.dashboardDataUrl);
}

Then in the dasboard component I'm calling the service for the data:

ngOnInit() {
   this.getReports();
}
getReports(): void {
    this.dashboardService.getDashboardReports().subscribe(reports => this.dashboardReports = reports);
}

For the DashboardReport class I've got:

export class DashboardReport{
    id: number;
    date: Date;
    overtime: number;
    project: string;
    superintendent: string;
    km: number;
    status: number;
}

Solution

  • The problem you have is in how you structure the object returned in your createDb function. For context, you're returning the following object:

    { DashboardReports }
    

    Note that this is simply a shortcut for the following:

    { DashboardReports: DashboardReports }
    

    This ends up configuring the following URL:

    'api/DashboardReports'
    

    It's obvious that this isn't the URL you're after. You want:

    'api/dashboard'
    

    In order to get that, you need to restructure the object you're returning. Here's one way to make it work in your example:

    export class InMemoryDataService implements InMemoryDbService {
        createDb() {
            const DashboardReports = ...;
    
            return { dashboard: DashboardReports };
        }
    }
    

    You'll notice in the tutorial you're following that the property name being used is heroes and the URL is api/heroes: the property name defines the URL endpoint that is used.