Angular: Как включить услугу в функциональный модуль - PullRequest
0 голосов
/ 03 мая 2020

После создания нового модуля для моих функциональных модулей и отделения их маршрутов от app.module.ts я получаю сообщение об ошибке:

    core.js:6185 ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(AppModule)[LoginService -> HttpClient -> HttpClient -> HttpClient]: 
  NullInjectorError: No provider for HttpClient!
NullInjectorError: R3InjectorError(AppModule)[LoginService -> HttpClient -> HttpClient -> HttpClient]: 
  NullInjectorError: No provider for HttpClient!
    at NullInjector.get (core.js:1076)
    at R3Injector.get (core.js:16629)
    at R3Injector.get (core.js:16629)
    at R3Injector.get (core.js:16629)
    at injectInjectorOnly (core.js:931)
    at Module.ɵɵinject (core.js:941)
    at Object.LoginService_Factory [as factory] (login.service.ts:10)
    at R3Injector.hydrate (core.js:16865)
    at R3Injector.get (core.js:16617)
    at NgModuleRef$1.get (core.js:36027)
    at resolvePromise (zone-evergreen.js:798)
    at resolvePromise (zone-evergreen.js:750)
    at zone-evergreen.js:860
    at ZoneDelegate.invokeTask (zone-evergreen.js:399)
    at Object.onInvokeTask (core.js:41264)
    at ZoneDelegate.invokeTask (zone-evergreen.js:398)
    at Zone.runTask (zone-evergreen.js:167)
    at drainMicroTaskQueue (zone-evergreen.js:569)
    at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:484)
    at invokeTask (zone-evergreen.js:1621)

Я создаю простой сервис входа в систему. Со страницы приветствия, как только пользователь нажмет кнопку «Play», появится страница входа. Однако всякий раз, когда я нажимаю соответствующую кнопку, я получаю вышеуказанную ошибку. И, похоже, начал прибывать после того, как я отделил функцию входа в функциональный модуль Тем не менее, моя служба имеет инжектор, определенный как

@Injectable({
providedIn:'root'

})

Таким образом, это означает, что будет создан только один экземпляр службы, и он будет использоваться во всем приложении. Впрочем, я сейчас сомневаюсь. Нужно ли мне объявить мой сервис где-нибудь в моем функциональном модуле? Я правильно импортировал

import { HttpClientModule } from '@angular/common/http';

в моем app.module.ts. Вот мой app.module.ts,

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
//import { RouterModule } from '@angular/router';
import { FormsModule }   from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';


import { AppComponent } from './app.component';
import { WelcomeComponent } from './home/welcome.component';
import { ActivityComponent } from './shared_component/activitiy-progress.component';
import { SmartWatchComponent } from './smart-watch/smart-watch.component';
import { SmartPhoneComponent } from './smart-phone/smart-phone.component';
import { SmartPhoneMenuComponent } from './smart-phone-menu/smart-phone-menu.component';
import { GameStartComponent } from './game-start/game-start.component';
//import { UserLoginComponent } from './user-login/user-login.component';
import { PageNotfoundComponent } from './page-notfound/page-notfound.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { UserSignupComponent } from './user-signup/user-signup.component';
import { UserCalendarComponent } from './user-calendar/user-calendar.component';
import { UserNewsComponent } from './user-news/user-news.component';
import { UserStorageComponent } from './user-storage/user-storage.component';
import { TodoListComponent } from './todo-list/todo-list.component';
import { AuthenticationModule } from './authentication/authentication.module';
import { LoginService } from './login.service';
import { AppRoutingModule } from './app-routing.module';


@NgModule({
  declarations: [
    AppComponent,
    WelcomeComponent,
    ActivityComponent,
    SmartWatchComponent,
    SmartPhoneComponent,
    SmartPhoneMenuComponent,
    GameStartComponent,
    PageNotfoundComponent,
    //ResetPasswordComponent,
    //UserLoginComponent,
    //UserSignupComponent,
    UserCalendarComponent,
    UserNewsComponent,
    UserStorageComponent,
    TodoListComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    FormsModule,
    ReactiveFormsModule,
    AuthenticationModule,
    AppRoutingModule

  ],
 // providers: [LoginService],
 providers : [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Вот мой функциональный модуль,

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {RouterModule} from '@angular/router';
import { FormsModule,ReactiveFormsModule }   from '@angular/forms';
import { UserLoginComponent } from '../user-login/user-login.component';
import { UserSignupComponent } from '../user-signup/user-signup.component';
import { ResetPasswordComponent } from '../reset-password/reset-password.component';


@NgModule({
  imports: [
    CommonModule,
    RouterModule.forChild([
      {path:'login',component: UserLoginComponent},
      {path:'signup',component: UserSignupComponent},
      {path:'reset-password',component: ResetPasswordComponent},
     // {path:'',redirectTo:'login',pathMatch:'full'}
    ]),
    FormsModule,
    ReactiveFormsModule
  ],
  declarations: [
    UserLoginComponent,
    UserSignupComponent,
    ResetPasswordComponent
  ],

})
export class AuthenticationModule { }

Вот сервис,

import { Injectable } from '@angular/core';
import {HttpClient,HttpErrorResponse} from '@Angular/common/http';
import { Observable, throwError } from 'rxjs';
import{map,catchError} from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})

export class LoginService {

  private loginUrl : string;
  constructor(private http:HttpClient){}



  getCurrentUserInfo(loginInfo) : Observable<any>{

    this.loginUrl = <my-url>; //for privacy I had to omit the URL
    console.log("this.loginUrl =", this.loginUrl);
    return this.http.get<any>(this.loginUrl)
    .pipe(map(response => response as any),
    catchError(this.handleError));
  }

  private handleError(err:HttpErrorResponse){
    let errorMessage = '';
    if(err.error instanceof ErrorEvent){
        errorMessage = `An error has occurred ${err.error.message}`;
    }else{
        errorMessage = `server returned code: ${err.status}, error message is: ${err.message} `;
    }

    console.error(errorMessage);
    return throwError(errorMessage);

   }
}

вот мой компонент входа в систему,

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { FormGroup, FormControl } from '@angular/forms';
import { LoginService } from '../login.service';


@Component({
  selector: 'app-user-login',
  templateUrl: './user-login.component.html',
  styleUrls: ['./user-login.component.css']
})
export class UserLoginComponent{
  testId = "testuser";
  testPwd = "pwd";
  userLoginForm = new FormGroup({
    userId : new FormControl(''),
    password : new FormControl('')

  });

constructor(private loginService : LoginService, private router : Router){}

  onLoginSubmit(){

    let loginInfo = {
      id : this.userLoginForm.value.userId,
      password : this.userLoginForm.value.password

    }

    if(loginInfo.id === "" || loginInfo.password === ""){
      alert("Please enter Id & passowrd");
    }else if(loginInfo.id === this.testId){
      if(loginInfo.password === this.testPwd){
        this.router.navigate(['/game-start']);
      }else{
        alert("password doesn't exist");
        this.router.navigate(['/reset-password']);
      }
    }else{
      alert("userId doesn't exist");
    }





    this.loginService.getCurrentUserInfo(loginInfo).subscribe({
      next : data => console.log("returned data : " , data)
    });

  }


}

Вот мой приветственный компонент. Всякий раз, когда он переходит на страницу входа, возникает ошибка.

import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
  selector : 'welcome',
  templateUrl: './welcome.component.html',
  styleUrls : ['./welcome.component.css']
})
export class WelcomeComponent {
  public pageTitle = 'SurvCovid App';
  submitted = false;
  constructor(private router: Router){}

  onSubmit(){
    this.submitted = true;
    this.processInitialServerCommunitaion();
  }

  processInitialServerCommunitaion(){
    //this.ngZone.run(() => this.router.navigate(['/app-start']))
    //this.router.navigate(['/game-start'], {state: {"Test":"test"}});
    this.router.navigate(['/login']);
   //alert('from game start');
  }
}

Вот мой модуль маршрутизации приложений,

import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import { UserCalendarComponent } from './user-calendar/user-calendar.component';
import { UserNewsComponent } from './user-news/user-news.component';
import { UserStorageComponent } from './user-storage/user-storage.component';
import { TodoListComponent } from './todo-list/todo-list.component';
import { SmartPhoneMenuComponent } from './smart-phone-menu/smart-phone-menu.component';
import { GameStartComponent } from './game-start/game-start.component';
//import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { PageNotfoundComponent } from './page-notfound/page-notfound.component';
import { WelcomeComponent } from './home/welcome.component';

const ROUTES = [
    //{path:'login',component: UserLoginComponent},
   // {path:'signup',component: UserSignupComponent},
    {path:'welcome',component: WelcomeComponent},
    {path:'calendar',component: UserCalendarComponent},
    {path: 'news',component:UserNewsComponent},
    {path: 'storage',component:UserStorageComponent},
    {path: 'todo-list',component:TodoListComponent},
    {path : 'smartPhone-menu',component:SmartPhoneMenuComponent},
    {path : 'game-start',component :GameStartComponent},
    {path:'',redirectTo:'welcome',pathMatch:'full'},
   // {path:'reset-password',component: ResetPasswordComponent},
    {path : '**',component : PageNotfoundComponent}
    /*{path:'**',redirectTo:'welcome', pathMatch: 'full'}*/
  ];

@NgModule({
    imports: [
        RouterModule.forRoot(ROUTES)
    ],
    exports : [RouterModule]
})

export class AppRoutingModule{}

Вот версии, которые я использую,

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.7
@angular-devkit/build-angular     0.900.7
@angular-devkit/build-optimizer   0.900.7
@angular-devkit/build-webpack     0.900.7
@angular-devkit/core              9.0.7
@angular-devkit/schematics        9.0.7
@ngtools/webpack                  9.0.7
@schematics/angular               9.0.7
@schematics/update                0.900.7
rxjs                              6.5.4
typescript                        3.7.5
webpack                           4.41.2

Я учусь Angular и совершенно потерян с этой проблемой. Я искал решение в подобных статьях Stakoverflow, но в основном все предлагали импортировать HttpClientModule, что я уже сделал. А также, кажется, никто не сталкивался с этим при маршрутизации / загрузке компонента при загрузке сервиса. Вот почему я чувствую, что это новая проблема. Поэтому любая помощь будет очень цениться.

Ответы [ 2 ]

0 голосов
/ 03 мая 2020

В вашем функциональном модуле объявите провайдера как

@NgModule({
  imports: [
    CommonModule,
    RouterModule.forChild([
      {path:'login',component: UserLoginComponent},
      {path:'signup',component: UserSignupComponent},
      {path:'reset-password',component: ResetPasswordComponent},
     // {path:'',redirectTo:'login',pathMatch:'full'}
    ]),
    FormsModule,
    ReactiveFormsModule
  ],
  declarations: [
    UserLoginComponent,
    UserSignupComponent,
    ResetPasswordComponent
  ],
  providers:[LoginService]
})
0 голосов
/ 03 мая 2020

Вы можете указать, что услуга должна предоставляться в модуле, изменив значение providedIn.

Заменить

@Injectable({
  providedIn: 'root',
})

На:

@Injectable({
  providedIn: AuthenticationModule,
})

Читать это статья для более подробной информации

...