0

I am trying to display some data to html component from an ASP .NET Core API using Angular and Typescript, the response are returning correct values and the promise work well.

The problem is the html page loads before the promise is resolved, so the values displayed are undefined.

What can i use to make the page loads after the promise is resolved and how?

fileshare.component.ts

export class FileShareComponent implements OnInit {

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private service: UserService,
    private http: HttpClient
  ) {

    const file: string = this.route.snapshot.queryParamMap.get('file');

    this.http.get(this.service.BaseURL + '/Share?IdentityString=' + file)
      .toPromise()
      .then(res => {
        this.service.sharedFormData = res as ShareModel;
        console.log(this.service.sharedFormData);
      });

  }

  ngOnInit() {

  }


}

fileshare.component.html

<pre><code class="hljs">Name:
{{service.sharedFormData.Name}}</code></pre>
<pre><code class="hljs">Description:
{{service.sharedFormData.Description}}</code></pre>
<pre><code class="hljs">Syntax:
{{service.sharedFormData.Syntax}}</code></pre>
<pre><code class="hljs">LastModified:
{{service.sharedFormData.LastModified | date: "HH:mm dd/MM/yyyy"}}</code></pre>
<pre><code class="hljs">Content:
{{service.sharedFormData.Content}}</code></pre>
<div class="form-group text-center mt-4">
    <button class="btn btn-dark" (click)="this.service.raw()" type="submit"><i class="fas fa-database"></i>
        Raw</button>
</div>

share-model.model.ts

export class ShareModel {
    Id:number;
    Name: string;
    Description: string;
    Syntax: string;
    IdentityString:string;
    LastModified: string;
    Content: string;
    FileId: number;
}
Eduard
  • 83
  • 6
  • are you getting values in `console.log(this.service.sharedFormData);` ? – Shashank Vivek Jan 05 '20 at 12:55
  • Try putting `this.changeDetectorRef.detectChanges()` inside `then()` block after `this.service.sharedFormData = res as ShareModel;`, but it shouldn't be required. Give it a try as well and let me know – Shashank Vivek Jan 05 '20 at 12:57
  • There are values in console.log(this.service.sharedFormData); but the values are displayed in console after they are requested by the html. Now il take a look at router resolver. – Eduard Jan 05 '20 at 13:12

2 Answers2

0

Since the FileShareComponent is the one triggering the service call you won't be able to prevent the component from initializing until after that call is complete unless you create a more complicated architecture of nested components.

I'd hide the values until after the Observable resolves. And I see no pressing reason to convert the Observable into a promise. Something like this:

export class FileShareComponent implements OnInit {
  // create a variable to determine whether screen is initialized
  screenInitialized = false;
  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private service: UserService,
    private http: HttpClient
  ) {
    const file: string = this.route.snapshot.queryParamMap.get('file');
    this.http.get(this.service.BaseURL + '/Share?IdentityString=' + file)
      // subscribe to Observable instead of converting it to a promise 
      .subscribe(res => {
        this.service.sharedFormData = res as ShareModel;
        // toggle initialized property
        this.initialized = true;
        console.log(this.service.sharedFormData);
      });
  }
  ngOnInit() {
  }
}

Now, just wrap your display template inside a div that is hidden until the data is loaded:

<div *ngIf="initialized">
    <pre><code class="hljs">Name:
    {{service.sharedFormData.Name}}</code></pre>
    <pre><code class="hljs">Description:
    {{service.sharedFormData.Description}}</code></pre>
    <pre><code class="hljs">Syntax:
    {{service.sharedFormData.Syntax}}</code></pre>
    <pre><code class="hljs">LastModified:
    {{service.sharedFormData.LastModified | date: "HH:mm dd/MM/yyyy"}}</code></pre>
    <pre><code class="hljs">Content:
    {{service.sharedFormData.Content}}</code></pre>
    <div class="form-group text-center mt-4">
        <button class="btn btn-dark" (click)="this.service.raw()" type="submit"><i class="fas fa-database"></i>
            Raw</button>
    </div>
</div>

I think that is the easiest way to get you going based on your current structure. If I were building it from scratch, I'd look into using a router resolver.

JeffryHouser
  • 39,401
  • 4
  • 38
  • 59
0

Or to put it simpler you can use the elvis operator ?. in your html template.

fileshare.component.html

<pre><code class="hljs">Name:
{{service?.sharedFormData?.Name}}</code></pre>
<pre><code class="hljs">Description:
{{service?.sharedFormData?.Description}}</code></pre>
<pre><code class="hljs">Syntax:
{{service?.sharedFormData?.Syntax}}</code></pre>
<pre><code class="hljs">LastModified:
{{service?.sharedFormData?.LastModified | date: "HH:mm dd/MM/yyyy"}}</code></pre>
<pre><code class="hljs">Content:
{{service?.sharedFormData?.Content}}</code></pre>
<div class="form-group text-center mt-4">
    <button class="btn btn-dark" (click)="this.service.raw()" type="submit"><i class="fas fa-database"></i>
        Raw</button>
</div>