Template rendering string as [object Object]

I have code in my ngOnInit to get the translation for some particular text. It calls the following function:

async getEmailTranslation() {
    const email$ = this.translate.get('SUPPORT_TRANSLATE.EMAIL');
    this.email = await firstValueFrom(email$);
    console.log(typeof this.email);

When I check the console, I am seeing "Email" and "string" returned from the two console.log() statements, which is exactly what I am expecting.

In the template, when I render {{ this.email }}, the template shows [object Object] instead of the string.

email is defined as:

email: string;

What am I missing?

The strange thing is with another translation, this is working as expected:

async getWebsiteTranslation() {
    const website$ = this.translate.get('SUPPORT_TRANSLATE.WEBSITE');
    this.website = await firstValueFrom(website$);

In this case, when displaying {{ this.website }} in the template, it is properly rendering the string I am expecting.

>Solution :

You’re probably coming from a different framework where Promises are used. You could solve your problem with Promises for sure, but Angular is pretty strongly opinionated towards Observables (from RxJS).

Observables are like Promises in the sense that they are used to handle asynchronous operations, but they have a few key differences, probably the most important of which are that Observables don’t run "automatically" if you don’t subscribe to them (unlike Promises which run even if you don’t call .then() or await), and that Observables can emit more than one value before they are done.

Here, the "Angular way" to do things is to:

  • Expose a public Observable to your html. Currently you’re trying to expose public email: string, but it would be better to expose the public email$: Observable<string> directly.

  • Then, in your template, use the async pipe to get the value of your email.

The html may look something like

<div *ngIf="email$ | async as email">
  My email is {{ email }}.

The *ngIf allows two things: first off, the div won’t be shown until email$ has emitted its first value, so you’ll never see a div with just "My email is ." or "My email is [null]." here. Second, using the "as" syntax, it creates a variable called email, whose value is whatever email$ emitted, available inside the div where the *ngIf is declared.

Leave a Reply