<ion-virtual-scroll> not updating when trying to update items

In my Ionic 5 / Angular app, I am displaying some items in an <ion-virtual-scroll> below.

I am retrieving loadedMessages from a ConversationsService which I am calling from my Typescript you can see below also:

<ion-virtual-scroll [items]="loadedMessages">
    <ion-item-sliding *virtualItem="let message" #slidingItem>
        <ion-item>
            <ion-label>
                <h2>{{ message.text}}</h2>
            </ion-label>
        </ion-item>
    </ion-item-sliding>
</ion-virtual-scroll>

On the same page, I have the below form. When the user fills out this form, they add a new Message to the Conversation, they are able to do this using the conversation.id.

    <form [formGroup]="form">
        <ion-item>
            <ion-textarea formControlName="message"></ion-textarea>
        </ion-item>
        <ion-button (click)="onSendMessage()">Send</ion-button>
    </form>

Here is my Typescript:

ngOnInit() {
    this.route.paramMap.subscribe(paramMap => {
      this.conversationsSub = this.conversationsService
        .getConversation(paramMap.get('conversationId'))
        .subscribe(conversation => {
          this.conversation = conversation;
          this.loadedMessages = this.conversation.messages;
          this.mechanic = this.usersService.getUserByUserId(this.conversation.mechanicId);
          this.form = new FormGroup({
            message: new FormControl(null, {
              updateOn: 'blur',
            })
          });
        });
    });
  }
  onSendMessage() {
    this.conversationsService.addMessageToConversation(this.conversation.id, this.form.value.message);
  }

As I mentioned, if I navigate to a different page, & then navigate back to Conversation-Detail, the <ion-virtual-scroll> shows the updated messages, but I want the scroll to update as soon as the user clicks the Send button, & the Message is added.

And here is my ConversationsService:

export class ConversationsService {

  private _conversations = new BehaviorSubject<Conversation[]>([
    new Conversation(
      'conversation1',
      'user3',
      'user1',
      [
        new Message('message1', 'Test message', 'user3', new Date(2018, 0O5, 0O5, 17, 23, 42, 11)),
        new Message('message2', 'Another message', 'user1', new Date(2018, 0O6, 0O5, 17, 23, 42, 11))
      ]),
    new Conversation(
      'conversation2',
      'user4',
      'user2',
      [
        new Message('message3', 'my  message', 'user4', new Date(2018, 0O7, 0O7, 17, 23, 42, 11)),
        new Message('message4', 'more messages', 'user2', new Date(2018, 0O7, 0O7, 17, 23, 42, 11)),
      ])
  ]);

  get conversations() {
    return this._conversations.asObservable();
  }

  constructor(private authService: AuthService, private usersService: UsersService) { }

  private createMessage(message: string): Message {
    return {
      id: Math.random().toString(),
      text: message,
      userId: this.authService.userId,
      timestamp: new Date(Date.now())
    };
  }

  getConversation(id: string) {
    return this.conversations.pipe(
      take(1),
      map(conversations => {
        return { ...conversations.find(conversation => conversation.id === id) };
      }));
  }

  getConversationToAddMessage(id: string) {
    return this._conversations.getValue().find(conversation => conversation.id === id);
  }  

  addMessageToConversation(conversationId: string, message: string) {
    this.getConversationToAddMessage(conversationId).messages.push(this.createMessage(message));
  }

  addConversation(mechanicId: string, message: string) {
    const newConversation = new Conversation(
      Math.random().toString(),
      this.authService.userId,
      mechanicId,
      [this.createMessage(message)]
    );

    return this.conversations.pipe(
      take(1),
      delay(1000),
      tap(conversations => {
        this._conversations.next(conversations.concat(newConversation));
      }));
  }
}

Can someone please tell me how I can resolve this problem? I can provide further context if required also. Thanks a lot!

1 Like