angularsocket.ioangular-ui-router

Angular textarea does not update data on time but the console shows it correctly


I use the service socket.io to emit and receive data. When the send button is clicked, it emits data and shows FENEmitInfo, then receives the data and shows FENSocketioGetCnt and FENSocketioFilterCnt.

The console shows data correctly and on time, but the textarea does not update all the data on time, there is a delay on showing the data the next time.

How can I fix this?

Data showing when the send button is clicked the first time:

Data showing when the send button is clicked the first time

Data showing when the send button is clicked the second time:

Data showing when the send button is clicked the second time

Data showing when the send button is clicked the third time:

Data showing when the send button is clicked the third time

This is app.component.html:

<div><textarea id="txtarlogAPI" class="border border-red-500 rounded w-full h-96" [value]="logAPIraw"></textarea></div>
<div><button id="btnsendemit01" class="p-1 px-1 border border-red-500 rounded" (click)="sendemit01()">send</button></div> 

This is app.component.ts:

import { Component, OnInit } from '@angular/core';
import {FormsModule} from '@angular/forms';
import {SvsocketService} from './svsocket.service'; 

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [FormsModule],
  templateUrl: './app.component.html', 
  styleUrl: './app.component.css'      
})

export class AppComponent {   
  constructor(
    private socketService: SvsocketService    
  ){}
  
  SocketioGetCnt: number = 0;
  SocketioFilterCnt: number = 0;   
  SocketioEmitCnt: number = 0;
  logAPIraw: string = "";
  
  ngOnInit() {          
     
    this.socketService.onMsgSocketAPIEmitInfo().subscribe((dt: string) => { 

      this.SocketioGetCnt = this.SocketioGetCnt + 1;
      console.log('FENSocketioGetCnt:'+this.SocketioGetCnt+', dataget:'+dt);
      this.logAPIraw += 'FENSocketioGetCnt:'+this.SocketioGetCnt+', dataget:'+dt+'\n';
      
      if((dt.substring(0, 13))=="API_Info_test"){ //(dt=="API_Info_test")
        this.SocketioFilterCnt = this.SocketioFilterCnt + 1;
        console.log('FENSocketioFilterCnt:'+this.SocketioFilterCnt+', datafilter:'+dt); 
        this.logAPIraw += 'FENSocketioFilterCnt:'+this.SocketioFilterCnt+', datafilter:'+dt+'\n';     
      }     
    
    });  
  }
  
  public sendemit01() {    
    this.SocketioEmitCnt = this.SocketioEmitCnt + 1;    
    this.socketService.sendMsgSocketFENEmitInfo("FEN_Info_test_" + this.SocketioEmitCnt.toString()); 
    console.log('FENEmitInfo' + " FEN_Info_test_" + this.SocketioEmitCnt.toString() + ' Finished'); 
    this.logAPIraw += 'FENEmitInfo' + " FEN_Info_test_" + this.SocketioEmitCnt.toString() + ' Finished'+'\n';
  }
}

This is svsocket.service.ts:

import { ApplicationRef, inject, Injectable } from '@angular/core';

import { first, Observable } from 'rxjs';
import {io, Socket} from 'socket.io-client';

@Injectable({
  providedIn: 'root'
})
export class SvsocketService {
  private socket: Socket;

  constructor() {         
    
    this.socket = io('http://localhost:3000', { autoConnect: false });

    inject(ApplicationRef).isStable.pipe(
      first((isStable) => isStable))
    .subscribe(() => { this.socket.connect() });
    
  }
  
  sendMsgSocketFENEmitInfo(message: string): void { 
    this.socket.emit('FENEmitInfo', message);
  }

  onMsgSocketAPIEmitInfo(): Observable<string> { 
    return new Observable((observer) => {
      this.socket.on('APIEmitInfo', (message: string) => {
        observer.next(message);
      });
    });
  }
}

Solution

  • Beside using async pipe, you could also use checkDetector markForChange

    export class AppComponent {
        logAPIraw: string;
    
        constructor(private cdr: ChangeDetectorRef) {}
    
        sendemit01() {
            // Your logic that updates the model
            this.logAPIraw = 'newValue';
    
            // Mark for check
            this.cdr.markForCheck();
        }
    }