angularreferenceprimengmessagesidebar

PrimeNG sidebar clears primeng messages. Why?


In my app.component.html I have

<div class="main">
    <button type="button" (click)="onShowNotificationSideBar()" label="Show"></button>  
    <p-sidebar [(visible)]="notificationSideBarVisible" position="right" [style]="{width:'50em'}">
        <button type="button" pButton pRipple (click)="showSuccess()" label="S" class="p-button-success"></button>        
        <button type="button" pButton pRipple (click)="showWarn()" label="W" class="p-button-warning"></button>
        <button type="button" pButton pRipple (click)="showError()" label="E" class="p-button-danger"></button>
        <h3>Messages</h3>
        <h5>{{messages}}</h5>
        <p-messages [(value)]="messages" [enableService]="false" ></p-messages>
    </p-sidebar>
    <p-toast position="center"></p-toast>
    <router-outlet></router-outlet>
</div>

in app.component.ts I have

import { Component } from '@angular/core';
import { Message, MessageService } from 'primeng/api';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  providers: [MessageService]
})
export class AppComponent {
  title = 'WECO';
  notificationSideBarVisible = false;

  constructor(private messageService: MessageService) {
    messageService.messageObserver.subscribe((m:Message | Message[])=>{
      if (!Array.isArray(m)){
        this.messages.push(m)
      }
      this.messages = [...this.messages];
    });
  }

  onShowNotificationSideBar(){
    this.notificationSideBarVisible=true;
  }

  count=0;

  messages : Message[] = [
    // { severity: 'success', summary: 'Success', detail: 'Message Content' },
    // { severity: 'info', summary: 'Info', detail: 'Message Content' },
    // { severity: 'warn', summary: 'Warning', detail: 'Message Content' },
    // { severity: 'error', summary: 'Error', detail: 'Message Content' }
  ];

  longSentence = 'Let’s end all this nonsense about how long sentences = run-on sentences. You can have a six-word run-on sentence (“I went shopping I ate donuts.”), while most of the sentences below are much, much longer than that and are not run-ons';//'And let’s end all this nonsense about how long sentences = run-on sentences. You can have a six-word run-on sentence (“I went shopping I ate donuts.”), while most of the sentences below are much, much longer than that and are not run-ons (except for a few examples like Jose Saramago).  But whether the sentence is grammatically correct isn’t nearly as important as whether the sentence is fun or beautiful.'

  showWarn(){
    let detail='User Deleted a Weco Rule';
    if (this.count++%5===0)
      detail = this.longSentence;
    this.messageService.add({severity:'warn', summary:'User Action', detail: detail});
  }

  showSuccess(){
    let detail = 'Weco Rule 123 Saved';
    if (this.count++%5===0)
      detail = this.longSentence;
    this.messageService.add({severity:'success', summary:'Service Call', detail:detail});
  }

  showError(){
    let detail = 'api-call:get-factories returned 404';
    if (this.count++%5===0)
      detail = this.longSentence;
    this.messageService.add({severity:'error', summary:'Service Call', detail:detail});
  }
}

If I open side bar and add some messages in it they appear, but when I close and reopen they are gone. Even though I can see that messages variable still has them. Why?
P.S. If I then add some more messages I only see the new ones.


Solution

  • The sidebar menu has a component called p-messages, if you check the element, you will note that the p-sidebar contents gets destroyed when you close.

    When you reopen the sidebar, the data stays the same, but the messages are destroyed.

    I think the p-messages component will only show the array references are getting changed, this might be due to the *ngFor inside the component with a trackBy, so we need to reset each array elements reference in memory, so that we trick p-messages into thinking that there are new messages in the list, for this we can use object destructuring! I will do this when the sidebar is opened (onShowNotificationSideBar)

    onShowNotificationSideBar() {
        this.notificationSideBarVisible = true;
        this.messages = [...this.messages.map(x => ({...x}))]; // <- creates new references for the array and its contents!
    }
    

    full code

    import { Component } from '@angular/core';
    import { Message, MessageService } from 'primeng/api';
    
    @Component({
      selector: 'sidebar-basic-demo',
      templateUrl: './sidebar-basic-demo.html',
      providers: [MessageService],
    })
    export class SidebarBasicDemo {
      title = 'WECO';
      notificationSideBarVisible = false;
    
      constructor(private messageService: MessageService) {
        messageService.messageObserver.subscribe((m: Message | Message[]) => {
          if (!Array.isArray(m)) {
            this.messages.push(m);
          }
          this.messages = [...this.messages];
        });
      }
    
      onShowNotificationSideBar() {
        this.notificationSideBarVisible = true;
        this.messages = [...this.messages.map(x => ({...x}))];
      }
    
      count = 0;
    
      messages: Message[] = [
        // { severity: 'success', summary: 'Success', detail: 'Message Content' },
        // { severity: 'info', summary: 'Info', detail: 'Message Content' },
        // { severity: 'warn', summary: 'Warning', detail: 'Message Content' },
        // { severity: 'error', summary: 'Error', detail: 'Message Content' }
      ];
    
      longSentence =
        'Let’s end all this nonsense about how long sentences = run-on sentences. You can have a six-word run-on sentence (“I went shopping I ate donuts.”), while most of the sentences below are much, much longer than that and are not run-ons'; //'And let’s end all this nonsense about how long sentences = run-on sentences. You can have a six-word run-on sentence (“I went shopping I ate donuts.”), while most of the sentences below are much, much longer than that and are not run-ons (except for a few examples like Jose Saramago).  But whether the sentence is grammatically correct isn’t nearly as important as whether the sentence is fun or beautiful.'
    
      showWarn() {
        let detail = 'User Deleted a Weco Rule';
        if (this.count++ % 5 === 0) detail = this.longSentence;
        this.messageService.add({
          severity: 'warn',
          summary: 'User Action',
          detail: detail,
        });
      }
    
      showSuccess() {
        let detail = 'Weco Rule 123 Saved';
        if (this.count++ % 5 === 0) detail = this.longSentence;
        this.messageService.add({
          severity: 'success',
          summary: 'Service Call',
          detail: detail,
        });
      }
    
      showError() {
        let detail = 'api-call:get-factories returned 404';
        if (this.count++ % 5 === 0) detail = this.longSentence;
        this.messageService.add({
          severity: 'error',
          summary: 'Service Call',
          detail: detail,
        });
      }
    }
    

    html

    <div class="main">
      <button type="button" (click)="onShowNotificationSideBar()" label="Show">
        show sidebar
      </button>
      <p-sidebar
        [(visible)]="notificationSideBarVisible"
        position="right"
        [style]="{width:'50em'}"
      >
        <button
          type="button"
          pButton
          pRipple
          (click)="showSuccess()"
          label="S"
          class="p-button-success"
        >
          success
        </button>
        <button
          type="button"
          pButton
          pRipple
          (click)="showWarn()"
          label="W"
          class="p-button-warning"
        >
          warn
        </button>
        <button
          type="button"
          pButton
          pRipple
          (click)="showError()"
          label="E"
          class="p-button-danger"
        >
          error
        </button>
        <h3>Messages</h3>
        <h5>{{messages}}</h5>
        <p-messages [(value)]="messages" [enableService]="false"></p-messages>
      </p-sidebar>
      <p-toast position="center"></p-toast>
    </div>
    

    Stackblitz Demo