angularngx-pagination

ngx-pagination broke whenever I am passing new data to child component


I am using ngx-pagination package for pagination of large list. I am using pagination pipe inside the template of child component.

When ever the child component receives new Data pagination controls will broke and it won't work.

but if I restart the app it works properly Pagination broke only when I request new data and pass it to child component as input property.

I messed with pagination controls component properties. I have also tried setting the total items in paginate pipe. I have also tried setting pagination controls a Id and passed it into paginate pipe. But above tries didn't work at all.

Please find the child code below.

component.ts

export class AgentUserConvComponent implements OnChanges {

  @Input() chatData: Conversation[] = [];
  @Input() searchText: string;
  @Input() country: string;
  @Output() sendIds = new EventEmitter<MessagesToBeReviewed[]>();
  listLoading = true;
  msgsToBeReviewed: MessagesToBeReviewed[] = [];
  messages: Array<Message> = [];
  user = this.cookieService.getCookie('email').split('@')[0].length > 0 ? this.cookieService.getCookie('email').split('@')[0] : 'vijay.rm';

  constructor(private socketService: SocketService, private cookieService: CookieService) {}

  ngOnChanges() {

  }

  getConverse(chat: Conversation) {
    this.messages = chat.conversation;
    this.socketService.getRealtimeUsers();
  }

  updateMsgIds(id: number, user: string) {
    this.msgsToBeReviewed = [...this.msgsToBeReviewed, {id, user}];
    console.log('messagesToBeReviewed', this.msgsToBeReviewed);
  }
  checkInReviewMsgs(id: number, user: string) {
    return this.msgsToBeReviewed.filter(msg => msg.id === id).length > 0;
  }
  reviewIds(chat: Conversation) {
    this.sendIds.emit(this.msgsToBeReviewed);
    this.msgsToBeReviewed = [];
    this.socketService.userClosedConversation();
  }

  reviewAll(chat: Conversation) {
    const ids = chat.getMsgIdsAll();
    console.log('messageId for review all', ids);
    this.sendIds.emit(ids);
    this.msgsToBeReviewed = [];
    this.socketService.userClosedConversation();
  }

  afterExpand(chat: Conversation) {
    // tslint:disable-next-line: max-line-length
    this.socketService.userOpenedConversation({mlUser: this.user, user: chat.user, ids: chat.getMsgIdsAll().map(msg => msg.id), country: this.country});
  }
}

component.html

<h1 *ngIf="chatData.length === 0">No Conversations Yet</h1>
<mat-accordion *ngIf="chatData.length > 0">
  <mat-expansion-panel
    (closed)="reviewIds(chat)"
    (opened)="getConverse(chat)"
    (afterExpand)="afterExpand(chat)"
    *ngFor="
      let chat of chatData
        | search: searchText
        | paginate: { itemsPerPage: 15, currentPage: p, id: 'paginate' }
    "
  >
    <mat-expansion-panel-header>
      <mat-panel-title>
        <div class="title-style">
          <h4>{{ chat.user }}</h4>
          <span class="occupy-empty-space"></span>
          <div class="active-users">
            <ng-container
              *ngIf="!chat.reviewed && chat.getReviewers().length > 0"
            >
              <div *ngFor="let reviewer of chat.getReviewers()">
                <div class="circle-dot-user" [matTooltip]="reviewer">
                  <span
                    >{{ reviewer.split(".")[0][0].toUpperCase()
                    }}{{ reviewer.split(".")[1][0].toUpperCase() }}</span
                  >
                </div>
              </div>
            </ng-container>
          </div>
        </div>
      </mat-panel-title>
    </mat-expansion-panel-header>
    <mat-divider></mat-divider>

    <main
      class="msger-chat"
      *ngFor="let message of messages"
      class="expansion-class"
    >
      <div class="msg left-msg" *ngIf="message.req.length > 0">
        <div
          class="msg-img"
          style="background-image: url('static/distML/assets/image/user.svg')"
        ></div>
        <div class="msg-bubble">
          <div class="msg-info">
            <div class="msg-info-name">{{ message.id }}</div>
            <div class="msg-info-time">
              {{ message.time | date: "dd/MMM/yyyy, HH:mm a" }}
            </div>
          </div>
          <div class="msg-text">
            {{ message.req }}
          </div>
        </div>
      </div>

      <div class="msg right-msg" *ngIf="message.res">
        <div
          class="msg-img"
          style="background-image: url('static/distML/assets/image/favicon.512x512.png'); background-size: 55px 55px;"
        ></div>
        <div
          class="msg-bubble"
          [ngClass]="{
            'msg-bubble-default': !checkInReviewMsgs(message.msgId, message.id),
            'msg-bubble-addedToReview': checkInReviewMsgs(
              message.msgId,
              message.id
            ),
            'msg-bubble-reviewed': message.IsReviewed
          }"
        >
          <div class="msg-info">
            <div class="msg-info-name">Bot</div>
            <div class="msg-info-time">
              {{ message.time | date: "dd/MMM/yyyy, HH:mm a" }}
              <span
                *ngIf="
                  message.priority === null || message.priority.length <= 0
                "
                class="circleDot"
                >0</span
              >
              <span *ngIf="message.priority != null" class="circleDot">{{
                message.priority
              }}</span>
            </div>
          </div>
          <div
            class="msg-text"
            [innerHTML]="message.res | bypassSanitization: 'html'"
          >
            {{ message.res }}
          </div>
          <div class="msg-info-name" style="margin-top: 5px">
            <button
              *ngIf="!message.IsReviewed"
              mat-flat-button
              class="add-to-review"
              (click)="updateMsgIds(message.msgId, message.id)"
            >
              <div class="button-style">
                <p>
                  {{
                    checkInReviewMsgs(message.msgId, message.id)
                      ? "Added to Review"
                      : "Add to Review"
                  }}
                </p>
                <span class="occupy-empty-space"></span>
                <div class="active-users">
                  <ng-container *ngIf="message.reviewers.length > 0">
                    <div *ngFor="let reviewer of message.reviewers">
                      <div
                        class="circle-dot-user-button"
                        [matTooltip]="reviewer"
                      >
                        <span
                          >{{ reviewer.split(".")[0][0].toUpperCase()
                          }}{{ reviewer.split(".")[1][0].toUpperCase() }}</span
                        >
                      </div>
                    </div>
                  </ng-container>
                </div>
              </div>
            </button>
            <mat-chip-list *ngIf="message.IsReviewed">
              <mat-chip
                color="primary"
                selected
                [matTooltip]="message.ReviewedBy.split('@')[0]"
              >
                Reviewed by
                {{
                  message.ReviewedBy.split(".")[0][0].toUpperCase() +
                    message.ReviewedBy.split(".")[1][0].toUpperCase()
                }}
              </mat-chip>
            </mat-chip-list>
          </div>
        </div>
      </div>
    </main>
    <div class="msg-overflow"></div>
    <mat-action-row *ngIf="!chat.reviewed">
      <button mat-button color="accent" (click)="reviewAll(chat)">
        Review All
      </button>
    </mat-action-row>
  </mat-expansion-panel>
</mat-accordion>

<pagination-controls
  id="paginate"
  autoHide="true"
  responsive="true"
  (pageChange)="p = $event"
  class="pageControls"
  *ngIf="chatData.length > 0"
></pagination-controls>

When New data passed to child component paginate control component should work properly as it worked when the app is initialized.


Solution

  • I am able to solve the issue. In my case I reused child component two times. I Used pagination controls inside child component. But the issue here is the pagination control is same instance where ever I am using the child component. And pagination controls component udate the UI with the last data it rececvied. Example: I have a reusable component. I am using this reusable component with two times inside two tabs. When ever I pass the data to this reusable components the data which rececevies last update the pagination controls component in all all places where ever I use the reausable component.Please check the solution I implemented.

    <h1 *ngIf="chatData.length === 0">No Conversations Yet</h1>
    <mat-accordion *ngIf="chatData.length > 0">
      <mat-expansion-panel
        (closed)="reviewIds(chat)"
        (opened)="getConverse(chat)"
        (afterExpand)="afterExpand(chat)"
        *ngFor="
          let chat of chatData
            | search: searchText
            | paginate: { itemsPerPage: 15, currentPage: isYetToBeReviewed ? p1 : p2, id: isYetToBeReviewed ? 'paginate1' : 'paginate2' }
        "
      >
        <mat-expansion-panel-header>
          <mat-panel-title>
            <div class="title-style">
              <h4>{{ chat.user }}</h4>
              <span class="occupy-empty-space"></span>
              <div class="active-users">
                <ng-container
                  *ngIf="!chat.reviewed && chat.getReviewers().length > 0"
                >
                  <div *ngFor="let reviewer of chat.getReviewers()">
                    <div class="circle-dot-user" [matTooltip]="reviewer">
                      <span
                        >{{ reviewer.split(".")[0][0].toUpperCase()
                        }}{{ reviewer.split(".")[1][0].toUpperCase() }}</span
                      >
                    </div>
                  </div>
                </ng-container>
              </div>
            </div>
          </mat-panel-title>
        </mat-expansion-panel-header>
        <mat-divider></mat-divider>
    
        <main
          class="msger-chat"
          *ngFor="let message of messages"
          class="expansion-class"
        >
          <div class="msg left-msg" *ngIf="message.req.length > 0">
            <div
              class="msg-img"
              style="background-image: url('static/distML/assets/image/user.svg')"
            ></div>
            <div class="msg-bubble">
              <div class="msg-info">
                <div class="msg-info-name">{{ message.id }}</div>
                <div class="msg-info-time">
                  {{ message.time | date: "dd/MMM/yyyy, HH:mm a" }}
                </div>
              </div>
              <div class="msg-text">
                {{ message.req }}
              </div>
            </div>
          </div>
    
          <div class="msg right-msg" *ngIf="message.res">
            <div
              class="msg-img"
              style="background-image: url('static/distML/assets/image/favicon.512x512.png'); background-size: 55px 55px;"
            ></div>
            <div
              class="msg-bubble"
              [ngClass]="{
                'msg-bubble-default': !checkInReviewMsgs(message.msgId, message.id),
                'msg-bubble-addedToReview': checkInReviewMsgs(
                  message.msgId,
                  message.id
                ),
                'msg-bubble-reviewed': message.IsReviewed
              }"
            >
              <div class="msg-info">
                <div class="msg-info-name">Bot</div>
                <div class="msg-info-time">
                  {{ message.time | date: "dd/MMM/yyyy, HH:mm a" }}
                  <span
                    *ngIf="
                      message.priority === null || message.priority.length <= 0
                    "
                    class="circleDot"
                    >0</span
                  >
                  <span *ngIf="message.priority != null" class="circleDot">{{
                    message.priority
                  }}</span>
                </div>
              </div>
              <div
                class="msg-text"
                [innerHTML]="message.res | bypassSanitization: 'html'"
              >
                {{ message.res }}
              </div>
              <div class="msg-info-name" style="margin-top: 5px">
                <button
                  *ngIf="!message.IsReviewed"
                  mat-flat-button
                  class="add-to-review"
                  (click)="updateMsgIds(message.msgId, message.id)"
                >
                  <div class="button-style">
                    <p>
                      {{
                        checkInReviewMsgs(message.msgId, message.id)
                          ? "Added to Review"
                          : "Add to Review"
                      }}
                    </p>
                    <span class="occupy-empty-space"></span>
                    <div class="active-users">
                      <ng-container *ngIf="message.reviewers.length > 0">
                        <div *ngFor="let reviewer of message.reviewers">
                          <div
                            class="circle-dot-user-button"
                            [matTooltip]="reviewer"
                          >
                            <span
                              >{{ reviewer.split(".")[0][0].toUpperCase()
                              }}{{ reviewer.split(".")[1][0].toUpperCase() }}</span
                            >
                          </div>
                        </div>
                      </ng-container>
                    </div>
                  </div>
                </button>
                <mat-chip-list *ngIf="message.IsReviewed">
                  <mat-chip
                    color="primary"
                    selected
                    [matTooltip]="message.ReviewedBy.split('@')[0]"
                  >
                    Reviewed by
                    {{
                      message.ReviewedBy.split(".")[0][0].toUpperCase() +
                        message.ReviewedBy.split(".")[1][0].toUpperCase()
                    }}
                  </mat-chip>
                </mat-chip-list>
              </div>
            </div>
          </div>
        </main>
        <div class="msg-overflow"></div>
        <mat-action-row *ngIf="!chat.reviewed">
          <button mat-button color="accent" (click)="reviewAll(chat)">
            Review All
          </button>
        </mat-action-row>
      </mat-expansion-panel>
    </mat-accordion>
    
    <div *ngIf="chatData.length > 0">
      <pagination-controls
      id="paginate1"
      autoHide="true"
      responsive="true"
      (pageChange)="p1 = $event"
      class="pageControls"
      *ngIf="isYetToBeReviewed"
    ></pagination-controls>
    </div>
    <div *ngIf="chatData.length > 0">
      <pagination-controls
      id="paginate2"
      autoHide="true"
      responsive="true"
      (pageChange)="p2 = $event"
      class="pageControls"
      *ngIf="!isYetToBeReviewed"
    ></pagination-controls>
    </div>