Reputation: 1071
I have a service that wraps HttpClient
. That service is called by a component. The problem is that when I inject the service in the component constructor it is undefined
. Moreover, the service constructor seems to not execute at all as a console.log
does not print anything. Any ideas?
@Injectable({
providedIn: 'root'
})
export class MyHttpService {
constructor(public httpx: HttpClient) {
console.log("in the constructor - " + this.httpx) // <-- this is never printed
}
call () {
let reqData = { act: 'R'};
this.httpx.post('/myurl', reqData).subscribe(result => {
console.log(result);
}, error => console.log('There was an error: '));
}
}
The related module is defined as follows:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { HttpClient } from '@angular/common/http';
import { MyHttpService } from './http.service';
@NgModule({
imports: [
CommonModule,
HttpClientModule,
HttpClient
],
declarations: [
MyHttpService
],
exports: [
MyHttpService
]
})
export class CoreServiceModule {}
The component that calls the service:
@Component({
selector: 'some-selector',
templateUrl: 'some-url.html'
})
export class MyComponent implements OnInit{
constructor(public http:MyHttpService){
console.log(http); // <-- this prints undefined
}
ngOnInit() {
let x = this.http.call(); // <-- this fails as http is undefined
}
}
And the component module:
@NgModule({
declarations: [MyComponent],
exports: [MyComponent],
imports: [BrowserModule, CoreServiceModule],
bootstrap: [MyComponent]
})
export class MyModule {}
Upvotes: 1
Views: 7871
Reputation: 21
I had a similar issue:
this.httpx is undefined
For my greatest surprise, changing the function in the service to arrow function solved the problem:
call = () => {
let reqData = { act: 'R'};
this.httpx.post('/myurl', reqData).subscribe(result => {
console.log(result);
}, error => console.log('There was an error: '));
}
Anytime something of this
is undefined, first thing I check is if "arrowing" the function helps. More times than what I'm comfortable with, it does. I must assume that this is the doing of the good-old javascript this-fiasco.
Upvotes: 0
Reputation: 6458
Note that I'm new to Angular, but I've done something similar recently and looking at my own similar project, I've spotted a few differences:
1. When injecting the httpClient, it's a private rather than public
constructor(private http: HttpClient) { }
2. I think you need to include
import { HttpClient } from '@angular/common/http';
at the top of your MyHttpService module.
3. Note that you've got the same module define twice under a different name:
HttpClientModule,
HttpClient
I'd remove one to tidiness sake.
Hope this helps.
UPDATE - 1:
This is what I have in my test app. Hopefully, you'll spot something different but it definitely works for me.
app.module.ts:
…
import { HttpClientModule } from '@angular/common/http';
import { HttpService } from './http.service';
…
@NgModule({
declarations: [
…
],
imports: [
…
HttpClientModule,
…
],
}],
providers: [HttpService],
bootstrap: [AppComponent]
})
export class AppModule { }
I create a separate file for my http client service.
http.service.ts:
…
import { HttpClient } from '@angular/common/http';
…
@Injectable({
providedIn: 'root'
})
export class HttpService {
private _loginUrl = "http://...";
…
// inject http client in constructor. Make sure it is imported.
constructor(private http: HttpService) { }
// Sample function
loginUser(user) {
return this.http.post<any>(this._loginUrl, user);
}
}
and from my view/component:
login.component.ts:
import { HttpService } from '../http.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
…
constructor(private _http: HttpService) {
}
ngOnInit() {
}
loginUser() {
this._http.loginUser(this.loginUserData).subscribe...
}
}
Upvotes: 2
Reputation: 1481
You should try something like that, do not forget to importe ModuleWithProviders
interface from @angular/core
.
export class CoreServiceModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: CoreServiceModule,
providers: [MyHttpService]
}
}
}
Note that you need to import this "shared module" in your app.module.ts, and when you declare it in the app.module, you must call forRoot() method. You are then able to use this singleton anywhere in your application without any risk to be re-instanciated.
Upvotes: 1