Reputation: 31
I'm following Jogesh Muppala's Angular course on Coursera, and I'm stuck at the beginning of Week 4, where he's using HttpClient to communicate with the server.
I've followed the instructions exactly, but his instructions seem to break my program. DishServices is a service that retrieves data from the server, and is injected into one of the components, which calls on the service to do the retrieval. However, whenever that call is made, I get nothing on the page and this in the console.
MenuComponent_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'getDishes' of undefined at MenuComponent.push../src/app/menu/menu.component.ts.MenuComponent.ngOnInit (menu.component.ts:18) at checkAndUpdateDirectiveInline (core.js:9250) at checkAndUpdateNodeInline (core.js:10514) at checkAndUpdateNode (core.js:10476) at debugCheckAndUpdateNode (core.js:11109) at debugCheckDirectivesFn (core.js:11069) at Object.eval [as updateDirectives] (MenuComponent_Host.ngfactory.js? [sm]:1) at Object.debugUpdateDirectives [as updateDirectives] (core.js:11061) at checkAndUpdateView (core.js:10458) at callViewAction (core.js:10699)
As it happens, I prefer to use the older style of writing providers, and it revealed an error there.
providers: [{provide: DishService, useValue: new DishService()},
{provide: PromotionService, useValue: new PromotionService()},
{provide: ProcessHTTPMessageService, useValue: new ProcessHTTPMessageService()},
{provide: 'BaseURL', useValue: baseURL}
],
There's an error at DishService(), saying that it has the wrong number of arguments. When I check DishService,
import {Dish} from '../shared/dish';
import {DISHES } from '../shared/dishes';
import {Observable, of} from 'rxjs';
import { delay } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';
import { baseURL } from '../shared/baseurl';
import { Injectable } from '@angular/core';
export class DishService {
constructor(private http: HttpClient) {
}
getDishes(): Observable<Dish[]>{
return this.http.get<Dish[]>(baseURL + 'dishes');
}
}
There's the HttpClient in the constructor, which implies that it needs an object like that to be instantiated. The tutorial does not specify to to provide a new HttpClient in the providers. I have tried switching to the new style of writing providers, with Injectable providedIn root, with no success.
EDIT: Code from MenuComponent
import { Component, OnInit, Inject } from '@angular/core';
import { Dish } from '../shared/dish';
import {DishService} from '../services/dish.service';
@Component({
selector: 'app-menu',
templateUrl: './menu.component.html',
styleUrls: ['./menu.component.scss']
})
export class MenuComponent implements OnInit {
dishes: Dish[];
constructor(private dishService: DishService, @Inject('BaseURL') private BaseURL) { }
ngOnInit() {
console.log("fkvjndf");
this.dishService.getDishes().subscribe(dishes => this.dishes = dishes);
}
}
EDIT:
Replaced
providers: [{provide: DishService, useValue: new DishService()},
{provide: PromotionService, useValue: new PromotionService()},
{provide: ProcessHTTPMessageService, useValue: new ProcessHTTPMessageService()},
{provide: 'BaseURL', useValue: baseURL}
],
With
providers: [{provide: DishService},
{provide: PromotionService},
{provide: ProcessHTTPMessageService},
{provide: 'BaseURL', useValue: baseURL}
],
and added
@Injectable({
providedIn: 'root'
})
to DishService.ts
only to get the same error message
MenuComponent_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'getDishes' of undefined at MenuComponent.push../src/app/menu/menu.component.ts.MenuComponent.ngOnInit (menu.component.ts:18) at checkAndUpdateDirectiveInline (core.js:9250) at checkAndUpdateNodeInline (core.js:10514) at checkAndUpdateNode (core.js:10476) at debugCheckAndUpdateNode (core.js:11109) at debugCheckDirectivesFn (core.js:11069) at Object.eval [as updateDirectives] (MenuComponent_Host.ngfactory.js? [sm]:1) at Object.debugUpdateDirectives [as updateDirectives] (core.js:11061) at checkAndUpdateView (core.js:10458) at callViewAction (core.js:10699)
Upvotes: 0
Views: 208
Reputation: 2251
I think you need to add @Injectable() decorator in your service class and also these after this code..
import {Dish} from '../shared/dish';
import {DISHES } from '../shared/dishes';
import {Observable, of} from 'rxjs';
import { delay } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';
import { baseURL } from '../shared/baseurl';
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class DishService {
constructor(private http: HttpClient) {
}
getDishes(): Observable<Dish[]>{
return this.http.get<Dish[]>(baseURL + 'dishes');
}
}
No need to place this service in provider options of NgModule decorator of root module (like : app.module) due to the 'providedIn' flag and must need to add HttpClientModule in imports options of NgModule decorator also. Hope this helps.
Upvotes: 0
Reputation: 1734
The problem is that you have defined a parameter in the constructor, but when you call new DishService()
you don't pass this value in. In general, you can simplify your providers section and should be able to fix your problem in the same turn.
providers: [
DishService,
PromotionService,,
ProcessHTTPMessageService,
{provide: 'BaseURL', useValue: baseURL}
],
If you don't need any special construction for your provider, you can just pass in the class and the dependency injection framework will take care of the dependencies for you.
I don't see why you should use the older style of writing providers
, but if you want to make it more complicated you need to use a factory, once you require dependencies. But as I see it there is no point in doing that in your case.
Upvotes: 1