Home > Net >  ERROR NullInjectorError: R3InjectorError(AppModule)[MessageService -> MessageService -> Messag
ERROR NullInjectorError: R3InjectorError(AppModule)[MessageService -> MessageService -> Messag

Time:12-17

I am converting an old angular 1 to angular 15, in VS code it compiles fine but I am getting this error in browser console. Browser displays a blank page.

I have checked If I need to add MessageService anywhere else in working old code but could not find any reference.

Getting this error in browser console

enter image description here

App.module.ts

import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from "@angular/forms";
import { HttpClientModule } from "@angular/common/http";
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { SecurityModule } from "./security/security.module";
import { AppComponent } from './app.component';
import { ToastModule } from 'primeng/toast'
import { ButtonModule } from 'primeng/button';
import { DialogModule } from 'primeng/dialog'
import { SystemInformationModule } from './system-information/system-information.module';
import { FooterComponent } from './shared/layouts/footer/footer.component';
import { appRouting } from './app-routing.module';
import { HeaderComponent } from './shared/layouts/header/header.component';
import { BodyComponent } from './shared/layouts/body/body.component';
import { MessagesService } from "./shared/services/messages/messages.service";
@NgModule({
  declarations: [
    AppComponent,
    BodyComponent,
    FooterComponent,
    HeaderComponent,
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    FormsModule,
    HttpClientModule,
    SecurityModule,
    SystemInformationModule,
    ToastModule,
    ButtonModule,
    DialogModule,
    appRouting
  ],
  providers: [MessagesService],
  bootstrap: [AppComponent]
})
export class AppModule { }

message.service.ts

import { Injectable } from "@angular/core";
import { Observer, Observable, Subject } from "rxjs";
import { Message } from "primeng/api";

@Injectable()
export class MessagesService {
  private shortGrowls = new Subject<any>();
  private stickyGrowls = new Subject<any>();
  private socket: Subject<MessageEvent>;

  shortGrowlAdded$ = this.shortGrowls.asObservable();
  stickyGrowlAdded$ = this.stickyGrowls.asObservable();

  constructor() { }

  addShortGrowl(message: any) {
    this.shortGrowls.next(message);
  }

  addStickyGrowl(message: any) {
      //console.log(`MessagesService  addStickyGrowl  message: ${JSON.stringify(message)}`);
    this.stickyGrowls.next(message);
  }

  public connect(url: string): Subject<MessageEvent> {
    if (!this.socket) {
      this.socket = this.create(url);
    }

    return this.socket;
  }

  private create(url: string): Subject<MessageEvent> {
    let ws = new WebSocket(url);

    let observable = Observable.create(
      (obs: Observer<MessageEvent>) => {
        ws.onmessage = observable.next.bind(obs);
        ws.onerror = obs.error.bind(obs);
        ws.onclose = obs.complete.bind(obs);

        return ws.close.bind(ws);
      });

    let observer = {
      next: (data: Object) => {
        if (ws.readyState === WebSocket.OPEN) {
          ws.send(JSON.stringify(data));
        }
      }
    };

    return Subject.create(observer, observable);
  }

  public addErrorMessages(source: string[]) {
      if (source != undefined && source != null && source.length > 0) {
          source.forEach((msg, i, a) => {
              this.shortGrowls.next({ severity: "error", summary: "Error", detail: msg });
          });
      }
  }

  public getErrorMessageFromResponse(resp: any): Message {
      //Default error message
      var msg: Message = { severity: "error", summary: "Internal Server Error", detail: "Internal Server Error" };

      //console.log(`getErrorMessage from resp: ${JSON.stringify(resp)}`);
      if (resp.statusText != undefined) {
          msg.summary = resp.statusText;
      }

      if (resp._body != undefined) {
          //console.log(`_body != undefined...`);
          try {
              var body = JSON.parse(resp._body);
              if (body.errDetails != undefined) {
                  if (body.errDetails.Message != undefined) {
                      msg.detail = body.errDetails.Message;
                  }
              }
          }
          catch(e) {
          }
      }

      if (resp.errDetails != undefined && resp.errDetails.Message != undefined) {
          msg.detail = resp.errDetails.Message;
      }

      //console.log(`getErrorMessage = ${JSON.stringify(msg)}`);
      return msg;
  }
}

app.component.ts

// #region imports
import { Component, Output, ElementRef } from "@angular/core";

import { Message } from "primeng/api";

import * as DomainModels from "./shared/models/domain";
import { MessagesService } from "./shared/services/messages/messages.service";
import { environment } from "../environments/environment";
import { UserAdGroupService } from "./shared/services/user-ad-groups/user-ad-groups.service";

declare var Ultima: any;
// #endregion

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
  providers: [MessagesService, UserAdGroupService]
})
export class AppComponent {
    title = "MicroScheduler";
    ribbon = environment.ribbon;

    @Output() userId: string;
    @Output() securityGroups: DomainModels.UserAdGroup[] = [];

    public activeMenuId: string;
    public themesVisible = false;
    public mobileMenuActive = false;
    // public shortlivedMessages: Message[] = [];
    // public stickyMessages: Message[] = [];
    public combinedMessages: Message[] = [];
    public showTagMaintenance: boolean = environment.showTagMaintenance;
    public showReports: boolean = environment.showReports;
    public showNetsMock: boolean = environment.showNetsMock;
    public majorVersion: number = environment.majorVersion;
    public release: number = environment.release;
    public componentBuild: number = environment.componentBuild;
    public noAccess: boolean = false;

    constructor( //private usersService: UsersService,
                 private appMessagesService: MessagesService,
                 private userAdGroupService: UserAdGroupService,
                 private el: ElementRef
    ) {
    }

    ngOnInit() {

        this.userAdGroupService.list().subscribe(resp => {
                //Handle errors
                if (resp.hasError) {
                    this.appMessagesService.addStickyGrowl(this.appMessagesService.getErrorMessageFromResponse(resp));
                }
                //Display info message if debugging
                if (resp.hasInfoMsg) {
                }

                //Update data
                this.securityGroups = resp.ReturnedItems;

                if (this.securityGroups != undefined && this.securityGroups.length > 0) {
                    this.userId = this.securityGroups[0].UserID;
                }
                else {
                    this.userId = "";
                    this.noAccess = true;
                }

                //this.userId = (this.securityGroups != undefined && this.securityGroups.length > 0) ? this.securityGroups[0].UserID : "";

                return resp;
            },
            response => {
                this.appMessagesService.addShortGrowl(this.appMessagesService.getErrorMessageFromResponse(response));
            }
        );

        this.appMessagesService.shortGrowlAdded$.subscribe(msg => {
            //var newMessages: Message[] = this.shortlivedMessages.concat();
            //newMessages.push(msg);
            msg.key="shortlivedMessages";
            this.combinedMessages.push(msg);
            //this.shortlivedMessages = newMessages;

            //this.shortlivedMessages.push(msg);
        });

        this.appMessagesService.stickyGrowlAdded$.subscribe((msg: Message) => {
            //this.stickyMessages.push(msg);
            msg.key="stickyMessages";
            this.combinedMessages.push(msg);
        });
    }

    ngAfterViewInit() {
        Ultima.init(this.el.nativeElement);
    }

    ngOnDestroy() {
    }

    toggleMenu(e: any) {
        this.mobileMenuActive = !this.mobileMenuActive;
        e.preventDefault();
    }
}

VS codes compiles well

enter image description here

CodePudding user response:

You are adding the MessagesService twice, in app.module and app.component provider's array.

Usually, when you create a service, that service is available in the entire project, for that, in the service metadata, you would require to add providedIn: 'root'.

For your case, if you want the service to be used in the entire project, then remove the MessagesService from providers and add the following to the service:

service

@Injectable({
  providedIn: 'root'
})
export class MessagesService {...}

app.module

  ...
  providers: [], //empty array
  bootstrap: [AppComponent]
})
export class AppModule { }

component

  ...
  styleUrls: ["./app.component.css"],
  providers: [UserAdGroupService] // no MessageService
})
export class AppComponent {

If you create a service by using the CLI, that metadata will be added by default.

Something to keep in mind is that, if you decide to add an specific service to the component's metadata (in this case UserAdGroupService), the data been handled in that service is not going to be available for other components, because, for this case, app.component has it's own instance of UserAdGroupService.

In other words, if component A and B has service C in their provider's metadata, and A passes some data to service C, B will not be aware of that data, same for the other way around, if B passes some data to service C, A will not known

CodePudding user response:

enter image description here

You have an issue with primeng component. Check on other components for MessageService of primeng/api package.

  • Related