So here's what's happening:
The property that you think is a string is actually an Object. When you're using the string interpolation syntax({{}}) on it in the template, Angular is calling the toString method on it. Calling toString on an Object results in [Object Object].
So once you get the response from the API, you'll need to make sure what exactly to print on the view. The stage name would probably be a field value on the response data that you're actually receiving from your service.
Below is an example mock(leveraging the JSONPlaceholder API) of how you'd go about doing it:
import { Component } from '@angular/core';
import { StageService } from './stage.service';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
stageData: any; // This would be assigned an Object that your service method results
constructor(private stageService: StageService) {}
async ngOnInit () {
this.stageData = await this.stageService.getStageData();
// Log it to the console to see it's structure and look for the property you want to use on the UI.
// For this specific example, the response data will have a name property that I'm using on the HTML(Template)
console.log('Got the Stage Data as: ', this.stageData);
}
}
In the template:
<!--
Here since the data is going to be assigned asynchronously
but the template would already be in the process of initialization,
I'm using the *ngIf directive to check.
If the stageData is still undefined, I'm displaying the elseBlock
-->
<div *ngIf="stageData; else elseBlock">
<h1>Stage Name</h1>
<p>Wrong Syntax: {{ stageData }} - Will print [Object object] as stageData is an Object and NOT A STRING</p>
<p>Right Syntax: {{ stageData.name }}</p>
</div>
<ng-template #elseBlock>
<h1>Loading...</h1>
</ng-template>
Here's a Sample StackBlitz for your ref.
PS: Pay close attention to the Comments.
{{ getNextStageName() || 'Not Available' | json}}$mymessage | async