Search code examples
angularangular-services

Global Messaging service in Angular problems


i am working on a web app using angular 7, and currently i am trying to use the Api interceptor to display an alert that an error has occured, which is working fine however, after adding the messaging service and messaging component, i tried to push the error message using the messaging(to format the message as i want in the component's template) however, it is not working and it is not giving me any errors. Anyway, here is the code

Api Interceptor.ts

    return next.handle(apiReq).pipe(
      retry(3),
      catchError(this.handleError)
    );
  }

  handleError(error: HttpErrorResponse) {
    let errorMessage = '';
    if (error.error instanceof ErrorEvent) {
      //client Side Error
      errorMessage = `Error: ${error.error.message}`;
    } else {
      //server side
      errorMessage = `Error: ${error.status}\nMessage: ${error.message}`;
    }

    window.alert(errorMessage);
    console.log('An Error has Occured');
    this.messageService.add(errorMessage);
    return throwError(errorMessage);
  }
}

This is the last part of the intecept and the beginning part of the handleError method.

message.service.ts

export class MessageService {
  messages: string[] = [];

  add(message: string) {
    this.messages.push(message);
  }

  clear() {
    this.messages = [];
  }

  constructor() { }
}

messages.component.ts

export class MessagesComponent implements OnInit {

  constructor(public messageService:MessageService) { }

  ngOnInit() {
  }

}

messages.component.html

<div *ngIf="messageService.messages.length">

  <h2>Messages</h2>
  <button class="clear"
          (click)="messageService.clear()">clear</button>
  <div *ngFor='let message of messageService.messages'> {{message}} </div>

</div>

My goal is to display the error messages dynamically formatted in the messages.component and pushed by the service that is injected in the Api Interceptor.

Thank you


Solution

  • Create a Subject in your messageService as follows, when ever an error gets added to the messages array you should call the next() method with messages array.

    export class MessageService {
      messages: string[] = [];
      messages$: new Subject<any>();
    
      add(message: string) {
        this.messages.push(message);
        this.messages$.next(this.messages);
      }
    
      clear() {
        this.messages = [];
      }
    
      constructor() { }
    }
    

    In your component, you should update the DOM whenever a change a message gets added to the messages array so you have to subscribe to the message$ subject as follows

    export class MessagesComponent implements OnInit {
      public messages: Array<any> = [];
      constructor(public messageService:MessageService) { }
    
      ngOnInit() {
        this.messageService.messages$.subscribe(messages => this.messages = messages);
      }
    
    }
    

    you html should be

    <div *ngIf="messages.length">
    
      <h2>Messages</h2>
      <button class="clear"
              (click)="messageService.clear()">clear</button>
      <div *ngFor='let message of messages'> {{message}} </div>
    
    </div>