Búsqueda de sitios web

angular - Error de 'No hay proveedor para AppComponent' al cargar


@NgModule({
  declarations: [
    AppComponent
    , DesktopComponent

  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpModule,
    AppRoutingModule,
    )
  ],
  providers: [LoginService, { provide: LocationStrategy, useClass: HashLocationStrategy } ,
    {
      provide: Http,
      useFactory: httpFactory,
      deps: [XHRBackend, RequestOptions, Router, AppComponent]
    }, MasterDataService, PersonService
  ],
  bootstrap: [AppComponent]

})
export class AppModule { }

Recibiendo el error Error: ¡No hay proveedor para AppComponent! cuando se agregan deps: [XHRBackend, RequestOptions, Router, AppComponent].

He usado este tutorial https://scotch.io/@kashyapmukkamala/using-http-interceptor-with-angular2 para implementar un interceptor. Ahora quiero llamar a un método en AppComponent desde la clase Interceptor.

Este es el método interceptor donde tuve que llamar al método de cierre de sesión de AppComponent

 intercept(observable: Observable<Response>): Observable<Response> {
        return observable.catch((err, source) => {
            if (err.status == 401) {

               localStorage.clear();
             this.appComp.logout();

            } else {
                return Observable.throw(err);
            }
        });

En el método Cerrar sesión del componente de la aplicación

logout() {
        console.log(" logging out");
        this.authenticated = false;
        $('#wrapper').attr("style", "display:none");
        this.loginService.logout();
    } 

Respuesta #1

El enfoque que estás intentando usar aquí no está alineado con los principios de diseño de Angular, los servicios deben estar diseñados como una preocupación separada y deben ser reutilizables por diferentes componentes y también testeables. Por lo tanto, los servicios no deben intentar interactuar con los componentes directamente. En su lugar, los componentes deben escuchar las respuestas o eventos de los servicios y luego decidir cómo reaccionar.

Recomiendo crear un servicio de notificaciones genérico que pueda usarse para enviar mensajes internos a lo largo de tu aplicación. Este servicio no se limita a enviar mensajes desde tu interceptor al AppComponent, sino que puede reutilizarse para comunicar eventos en diversas partes de tu aplicación.

Aquí hay un ejemplo de un servicio de notificación simple, este servicio debe ser inyectado tanto en tu interceptor como en el AppComponent:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Notification } from './notification';

@Injectable()
export class NotificationService {
    private notificationSubject = new Subject<Notification>();
    public notifications = this.notificationSubject.asObservable();

    notify(notification: Notification): void {
        this.notificationSubject.next(notification);
    }
}

La clase Notification se ve así:

export class Notification {
    message: string;
    status: NotificationStatus;

    constructor(message?: string, status?: NotificationStatus) {
        this.message = message;
        this.status = status;
    }
}

export enum NotificationStatus {
    Success = 0,
    Loading = 1,
    Confirm = 2,
    Error = 3, 
    Unauthorized = 4
}

Entonces, cuando quieras enviar un mensaje, inyecta el servicio de notificaciones y llama al método notify:

if (err.status == 401) {
    this.notificationService.notify(new Notification('Unauthorized', NotificationStatus.Unauthorized));
    return Observable.empty();
}

Tu AppComponent puede entonces suscribirse a los eventos de tu servicio de notificaciones:

this.notificationService.subscribe(notification => { 
    if(notification.status == NotificationStatus.Unauthorized) {
        //Handle any unauthorized errors here like and call logout() method
    }
});

Respuesta #2

En Providers, por qué estás usando 'AppComponent', no puedes usar Component en Providers

Prueba el siguiente código:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import {HttpModule, Http, XHRBackend, RequestOptions} from '@angular/http';

import {AppComponent} from "./app.component";
import {httpFactory} from "./http.factory";

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        FormsModule,
        HttpModule
    ],
    bootstrap: [AppComponent],
    providers: [
        {
            provide: Http,
            useFactory: httpFactory,
            deps: [XHRBackend, RequestOptions]
        }
    ]
})
export class AppModule { }