I am trying to extend the Angular2 HTTP module in order to create an HTTP interceptor of sorts.. the only problem is when I try to extend this module I get the following error:
No provider for ConnectionBackend!
I have no idea why this is happening and can't seem to get this error to go.
Here is my custom HTTP module:
import { Injectable } from "#angular/core";
import { Http, ConnectionBackend, RequestOptions, Request, RequestOptionsArgs, Response } from "#angular/http";
import { Observable } from "rxjs";
#Injectable()
export class HttpInterceptor extends Http {
constructor(
backend: ConnectionBackend,
defaultOptions: RequestOptions
) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
console.log('request...');
return super.request(url, options).catch(res => {
// do something
});
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
console.log('get...');
return super.get(url, options).catch(res => {
// do something
});
}
}
And here is my app.module.ts file:
import 'app/rxjs-extensions';
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpModule } from "#angular/http";
import { FormsModule } from "#angular/forms";
import { AuthGuard } from "./guards/auth.guard";
import { routing } from "./app.routing";
import { AppComponent } from './app.component';
import { HomeComponent } from "./components/home/HomeComponent";
import { LoginComponent } from "./components/login/LoginComponent";
import { NavBarComponent } from "./components/navbar/NavBarComponent";
import { ProductComponent } from "./components/catalog/products/ProductComponent";
import { GlobalEventsManager } from "./services/globalEventsManager.service";
import { AuthService } from "./services/auth.service";
import { ToastModule } from 'ng2-toastr/ng2-toastr';
import { LeftNavComponent } from "./components/left-nav/left-nav-component";
import { SettingsComponent } from "./components/settings/settings-component";
import { UsersComponent } from "./components/users/users-component";
import { OptionsComponent } from "./components/catalog/options/OptionsComponent";
import { CategoriesComponent } from "./components/catalog/categories/CategoriesComponent";
import { ManufacturersComponent } from "./components/catalog/manufacturers/ManufacturersComponent";
import { ProductSearchComponent } from "./components/catalog/products/directives/ProductSearchComponent";
import { ProductListComponent } from "./components/catalog/products/directives/ProductListComponent";
import { ProductService } from "./services/product.service";
import { HttpInterceptor } from "./services/HttpInterceptor.service";
#NgModule({
imports: [
BrowserModule,
HttpModule,
FormsModule,
routing,
ToastModule
],
declarations: [
AppComponent,
HomeComponent,
LoginComponent,
NavBarComponent,
ProductComponent,
ProductSearchComponent,
ProductListComponent,
LeftNavComponent,
SettingsComponent,
UsersComponent,
OptionsComponent,
CategoriesComponent,
ManufacturersComponent
],
providers: [
AuthService,
AuthGuard,
GlobalEventsManager,
ProductService,
HttpInterceptor
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
I have tried placing the my HttpInterceptor module inside the providers array in this file and this still doesn't work. Can anyone tell me why this is not working?
Thanks!
You have to construct and provide your extended class yourself like so:
ProductService,
{
provide: HttpInterceptor,
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) =>
new HttpInterceptor(backend, defaultOptions),
deps: [XHRBackend, RequestOptions]
}
],
Also, if you want to inject another MyService in there, you can do
{
deps: [XHRBackend, RequestOptions, MyService],
provide: HttpInterceptor,
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, myService: MyService) =>
new HttpInterceptor(backend, defaultOptions, myService),
},
After that, just inject MyService in the HttpInterceptor
Related
I'm a beginner in Angular, and use BreadCrumb in my project. I have no problem with other pages, but when I want to show my child node details, I can only see the product id.
My project is here, and this is my code.
core.module.ts:
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { NavBarComponent } from './nav-bar/nav-bar.component';
import { RouterModule } from '#angular/router';
import { TestErrorComponent } from './test-error/test-error.component';
import { NotFoundComponent } from './not-found/not-found.component';
import { ServerErrorComponent } from './server-error/server-error.component';
import { ToastrModule } from 'ngx-toastr';
import { BreadcrumbModule } from 'xng-breadcrumb';
import { SectionHeaderComponent } from './section-header/section-header.component';
#NgModule({
declarations: [NavBarComponent, TestErrorComponent, NotFoundComponent, ServerErrorComponent, SectionHeaderComponent],
imports: [
CommonModule,
RouterModule,
BreadcrumbModule,
ToastrModule.forRoot({
positionClass: 'toast-bottom-right',
preventDuplicates: true
})
],
exports: [NavBarComponent, SectionHeaderComponent]
})
export class CoreModule { }
shop.routing.module.ts:
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { Routes, RouterModule } from '#angular/router';
import { ShopComponent } from './shop.component';
import { ProductDetailsComponent } from './product-details/product-details.component';
const routes: Routes = [
{ path: '', component: ShopComponent },
{ path: ':id', component: ProductDetailsComponent, data: { breadCrumb: { alias: 'productDetails' } }}
];
#NgModule({
declarations: [],
imports: [
CommonModule,
RouterModule.forChild(routes)
],
exports: [RouterModule]
})
export class ShopRoutingModule { }
product-details.component.ts:
import { Component, OnInit } from '#angular/core';
import { IProduct } from '../../shared/models/product';
import { ShopService } from '../shop.service';
import { ActivatedRoute } from '#angular/router';
import { BreadcrumbService } from 'xng-breadcrumb';
#Component({
selector: 'app-product-details',
templateUrl: './product-details.component.html',
styleUrls: ['./product-details.component.scss']
})
export class ProductDetailsComponent implements OnInit {
product: IProduct;
constructor(private shopService: ShopService, private activatedRoute: ActivatedRoute, private bcService: BreadcrumbService) { }
ngOnInit(): void {
this.loadProduct();
}
loadProduct() {
this.shopService.getProduct(+this.activatedRoute.snapshot.paramMap.get('id')).subscribe(product => {
this.product = product;
this.bcService.set('#productDetails', product.name);
}, error => {
console.log(error);
});
}
}
I gave my project link to check all of my code if you need it. Thanks for the help!
This happened when I debugged my project on chrome:
seems you have a typing error,
in shop-routing-module.ts it should be breadcrumbnot breadCrumb
data: { breadcrumb: { alias: 'productDetails' } },
I'm working on angular-cli. I got following errors.
ERROR in ./src/app/app.module.ts
Module not found: Error: Can't resolve '#angular/router/src/router_module' in
'E:\xampp\Angular-cli\Login\src\app'
# ./src/app/app.module.ts 13:0-69
# ./src/main.ts
# multi webpack-dev-server/client?http://localhost:4200 ./src/main.ts
I've this library #angular/router/src/router_module in my node_module. What is missing?
Here are required files.
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { AdminAccount } from './admin/admin.component';
import { LoginForm } from './login/login.component';
import { FileData } from './filedata/filedata.component';
import { ROUTER_PROVIDERS } from "#angular/router/src/router_module";
import { RouterModule, Routes, ROUTES } from "#angular/router";
import { Http, Response } from "#angular/http";
import { Route } from './router/router.component';
#NgModule(
{
imports: [RouterModule ,Route, BrowserModule, Http, Response, AdminAccount, LoginForm, FileData, Route],
declarations: [AppComponent],
providers: [ROUTER_PROVIDERS],
bootstrap: [AppComponent]
})
export class AppModule { }
router.component.ts
import { Component, OnInit } from '#angular/core';
import { RouterModule } from "#angular/router";
import { LoginForm } from "../login/login.component";
import { AdminAccount } from "../admin/admin.component";
export const Route = RouterModule.forRoot(
[
{ path: '/', component: LoginForm },
{ path: '/admin', component: AdminAccount }
]);
app.component.ts
import { Component } from "#angular/core";
import { LoginForm } from "./login/login.component";
import { AdminAccount } from "./admin/admin.component";
import { Routes, RouterModule } from "#angular/router";
import { FileData } from "./filedata/filedata.component";
#Component(
{
selector: "root",
templateUrl: "./app.component.html",
})
export class AppComponent {}
If need more file let me know.
#Fahad Nasir Here's AdminAcount.
import { Component, OnInit } from '#angular/core';
import { Router } from "#angular/router";
#Component(
{
selector: "admin",
templateUrl: "./admin.component.html",
})
export class AdminAccount
{
adminUser = document.cookie.split("??")[0];
adminPass = document.cookie.split("??")[1];
constructor(public router: Router)
{
if (document.cookie !== undefined)
{
if (this.adminUser == "admin" && this.adminPass == "admin")
{
console.log("Welcome!");
}
else
{
this.router.navigate(["Loginform"]);
console.log("Redirect!");
}
}
else
{
console.log("Error: Undefined Login!");
}
}
}
Here Have a look
project Structure
Error Information
This is the error i am getting , when i broadcast the message from http extender service to the app component.
Loading Interceptor(http extender)
this is my http extender ,i am unable to broadcast the messages to App component from here ,but i am able to broadcast the messages from the child components to App component ,please see the image for the error information and project structure
import { Injectable } from '#angular/core';
import { Http, RequestOptions, RequestOptionsArgs, Response, ConnectionBackend } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { EventsEmitter } from './eventsEmitter';
#Injectable()
export class LoadingInterceptor extends Http {
private currentRequests: number = 0;
public constructor(_backend: ConnectionBackend, _defaultOptions: RequestOptions, private eventsEmitter: EventsEmitter) {
super(_backend, _defaultOptions);
}
public get(url: string, options?: RequestOptionsArgs): Observable<Response> {
this.incrementRequestCount();
var response = super.get(url, options);
response.subscribe(null, error => {
this.decrementRequestCount();
}, () => {
this.decrementRequestCount();
});
return response;
}
private decrementRequestCount() {
if (--this.currentRequests == 0) {
this.eventsEmitter.broadcast('loading-complete');
}
}
private incrementRequestCount() {
if (this.currentRequests++ == 0) {
this.eventsEmitter.broadcast('loading-started');
}
}
}
App Component
I am listening the events broadcasted in the app component to show the loader gif on the screen
import { Component } from '#angular/core';
import { EventsEmitter } from './assets/scripts/services/eventsEmitter';
import { ToasterService } from 'angular2-toaster';
#Component({
selector: 'my-app',
templateUrl:'app/app.component.html'
})
export class AppComponent {
private toasterService: ToasterService;
private message: any;
private active: any;
constructor(toasterService: ToasterService, private eventsEmitter: EventsEmitter) {
this.toasterService = toasterService;
this.eventListners();
}
eventListners() {
this.eventsEmitter.on<string>('loading-complete')
.subscribe(message => {
this.active = false;
});
this.eventsEmitter.on<string>('loading-started')
.subscribe(message => {
this.active = true;
});
}
}
Event Emitter
this is the event emittter i am using to broadcast the events
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
interface EventsEmitterInterface {
key: any;
data?: any;
}
export class EventsEmitter {
private _eventBus: Subject<EventsEmitterInterface>;
constructor() {
this._eventBus = new Subject<EventsEmitterInterface>();
}
broadcast(key: any, data?: any) {
this._eventBus.next({ key, data });
}
on<T>(key: any): Observable<T> {
return this._eventBus.asObservable()
.filter(event => event.key === key)
.map(event => <T>event.data);
}
}
App Module
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { LocationStrategy, HashLocationStrategy } from '#angular/common';
import { HttpModule, JsonpModule, Http, RequestOptions, XHRBackend, RequestOptionsArgs, Response, ConnectionBackend} from '#angular/http';
import { AppRoutingModule } from './app.routes';
import { AppComponent } from './app.component';
import { LoginComponent } from './components/login/login.component';
import { LoadingInterceptor } from './assets/scripts/services/loadingInterceptor';
import { EventsEmitter } from './assets/scripts/services/eventsEmitter';
import { ToasterModule, ToasterService } from 'angular2-toaster';
#NgModule({
imports: [AppRoutingModule, BrowserModule, FormsModule, ReactiveFormsModule, HttpModule, JsonpModule, ToasterModule ],
declarations: [AppComponent, LoginComponent],
bootstrap: [AppComponent],
providers: [EventsEmitter,LoadingInterceptor,
{
provide: Http,
useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions, eventsEmitter: EventsEmitter) => new LoadingInterceptor(xhrBackend, requestOptions, eventsEmitter),
deps: [XHRBackend, RequestOptions]
},{ provide: LocationStrategy, useClass: HashLocationStrategy }]
})
export class AppModule { }
I am stuck here for many days, it would be really helpful if you could help me resolve this issue
You forgot to add EventsEmitter dependency within your useFactory provider:
deps: [XHRBackend, RequestOptions]
It shoul be:
deps: [XHRBackend, RequestOptions, EventsEmitter]
That's why your LoadingInterceptor constructor gets undefined for EventsEmitter dependency
So, I'm currently trying to send a HTTP request, I'm doing everything exactly like in official guide and it's wont work (as usual when you make deal with Angular2)
Here is my app.module
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { RouterModule, Routes } from '#angular/router';
import { HttpModule, JsonpModule } from '#angular/http';
import { AppComponent } from './app.component';
import { PageComponent } from './modules/Affiliate/affiliate.component';
import { NotFoundComponent } from './not-found.component';
const routes: Routes =
[
{ path: 'page', component: PageComponent },
{ path: '404', component: NotFoundComponent },
{ path: '**', redirectTo: '404' }
];
#NgModule({
imports: [
BrowserModule,
RouterModule.forRoot(routes),
HttpModule,
JsonpModule
],
declarations: [
AppComponent,
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
And here is my service, where I'm trying to send a http request
import { Injectable } from '#angular/core';
import { Headers, Http } from '#angular/http';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class GridService {
constructor(private http: Http) { }
getTableRaws(url): Promise<any> {
return this.http.get(url)
.toPromise()
.then(response => response.json().data as any)
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
Any ideas, please
Following the docs, I guess you missed the data type for the url param:
getTableRaws(url: string): Promise<any> {
...
}
UPDATE:
You need to add GridService as a provider in app.module. Refer to this SO answer.
If you have made these changes then update your code in the question and also provide the contents of app.component here.
Here is the solution that works for me:
constructor(#Inject(Http) private http: Http) {}
I am trying to implement a global handler to manage HTTP errors in Angular2. Going through few reference: http://restlet.com/blog/2016/04/18/interacting-efficiently-with-a-restful-service-with-angular2-and-rxjs-part-3/ and https://blog.tomasandtomas.com/angular-2-http-interceptors-7e2d74b7f14e#.nxgxijnqu , I made the following:
--------------------------------------------------------------------
// Logger service - which will be able to send the error to server or log to console
import { Http } from '#angular/http';
import { Injectable } from '#angular/core';
import { Response } from '#angular/http';
#Injectable()
export class ErrorLogService {
public logError(error: any): void {
// custom error handling here
console.log(error);
}
}
--------------------------------------------------------------------
// This is the Custom HTTP that extends Http module
import { Injectable } from '#angular/core';
import { Http, ConnectionBackend, Request, RequestOptions, RequestOptionsArgs } from '#angular/http';
import { ErrorLogService } from '../ErrorHandling/error.log.service';
import { Observable } from 'rxjs/Rx';
#Injectable()
export class CustomHttp extends Http {
constructor(_backEnd: ConnectionBackend,
defaultOptions: RequestOptions, private errorLogService: ErrorLogService) {
super(_backEnd, defaultOptions);
}
get(url: string, options?: RequestOptionsArgs): Observable<any> {
return super.request(url, options)
.catch((error: any): any => {
this.errorLogService.logError(error);
return Observable.empty();
})
.finally(() => {
console.log('Done');
});
}
}
--------------------------------------------------------------------
// This is the service that call the api to get data.
import { Http, Response } from '#angular/http';
import { Injectable } from '#angular/core';
import { IAsset } from './asset';
import { AppSettings } from '../app.settings';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class AssetService {
private _cid = 1234;
private _total = 774;
private _pageIndex = 1;
constructor(private _http: Http) { }
getAssets(pageIndex: number): Promise<IAsset[]> {
this._pageIndex = pageIndex;
let _assetApi = `${AppSettings.GET_CONFIG('assets')}?1cid=${this._cid}&count=${this._total}&index=${this._pageIndex}`;
return this._http.get(_assetApi)
.toPromise()
.then(response => response.json() as IAsset[]);
}
}
--------------------------------------------------------------------
//This is how custom Http is injected in the app module
import { NgModule, APP_INITIALIZER, ErrorHandler } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpModule } from '#angular/http';
import { Http, XHRBackend, RequestOptions } from '#angular/http';
import { AppComponent } from './app.component';
import { WelcomeComponent } from './home/welcome.component';
import { ProductModule } from './products/product.module';
import { AppRoutingModule } from './app.routing.module';
import { ErrorLogService } from './shared/ErrorHandling/error.log.service';
import { CustomHttp } from './shared/Http/custom.http.service';
#NgModule({
imports: [
BrowserModule,
HttpModule,
AppRoutingModule,
ProductModule
],
declarations: [
AppComponent,
WelcomeComponent
],
providers: [
ConfigService,
AuthService,
ErrorLogService,
{
provide: Http,
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, _errorLogService: ErrorLogService) => {
return new CustomHttp(backend, defaultOptions, _errorLogService);
},
deps: [XHRBackend, RequestOptions]
}
],
bootstrap: [AppComponent],
})
export class AppModule { }
Now the problem is that I anytime there is a 500 internal server error on my data service, it is caught by by the CustomHttp, but the this.errorLogService.logError(error); >> errorLogService is undefined and does not invoke the logError on it.
I am using the Angular 2.0.0.0.
Any pointers on this issue? - Thanks.
You need to add ErrorLogService to CustomHttp's provider deps:
providers: [
ConfigService,
AuthService,
ErrorLogService,
{
provide: Http,
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, _errorLogService: ErrorLogService) => {
return new CustomHttp(backend, defaultOptions, _errorLogService);
},
deps: [XHRBackend, RequestOptions, ErrorLogService] <-- this
}
],