Ibanez1408
Ibanez1408

Reputation: 5058

How to append new line of text to a text area in Angular 2

I have a service that handles messages from my server and created an observable for it like so:

serverMessage$: Observable<string>;
private serverMessageSubject: Subject<string>;

constructor() {
this.serverMessageSubject = new Subject<string>();
this.serverMessage$ = this.serverMessageSubject.asObservable();
}

setServermessage(message: string) {
    this.serverMessage = message;
    this.serverMessageSubject.next(this.serverMessage);
}

I am waiting for this string in my component and adding it to my textarea like so:

.ts file

serverMessage: string;

constructor(
    private cs: CommonService
) {
    this.cs.serverMessage$.subscribe((message: string) => {
    this.serverMessage += message;
    });
  }

.html file

<div class="col-md-12" *ngIf="serverMessage">
    <textarea style="width: 100%" cols="50" rows="10">{{ serverMessage }}</textarea>
</div>

This is where the setServermessage is called:

signalr.service.ts

onMessageReceived(serverMessage: string) {
    this.cs.setServermessage(serverMessage);
  }

The problem is when I log the messages in my textarea, it outputs the previous message and the current message thus making the outputs duplicated. I just want to append the new messages to the old messsages in my textarea.

Upvotes: 1

Views: 2644

Answers (1)

SaMiCoOo
SaMiCoOo

Reputation: 357

Your case is a perfect one for using scan operator

Instead of using a local variable and concatinating strings you can do something like this:

Your service will remain as it is. But you will change your component logic to this


// serverMessage: string; No need anymore
serverMessage$: Observable<string>;
constructor(
    private cs: CommonService
) {
    this.serverMessage$ = this.cs.serverMessage$
    .pipe(scan((accumaltor, message) => accumator + message))
    // .subscribe((message: string) => {
      // this.serverMessage += message;

    // });
    // No need to subscribe anymore as we will be using the `async pipe`, but if you need `serverMessage` for something else
    // You can remove the comments and make it `=` not `+=` as the messages are already concatinated
  }

And then you can do something like this in your template


<!-- notice the async pipe here, remove the need to unsubscribe() at ngDestroy() -->
<div class="col-md-12" *ngIf="serverMessage$ | async as serverMessage">
    <textarea style="width: 100%" cols="50" rows="10">{{ serverMessage }}</textarea>
</div>

Upvotes: 3

Related Questions