0

I have the following service method in Angular 7:

public getTopPosts(): Observable<Payload<PostResponse>> {

  return this.httpClient.get<Payload<PostResponse>>('/top-posts');

}

On the component I have:

export class TopPostsComponent implements OnInit {

  posts: PostModel[] = [];

  constructor(private postService: PostService) { }

  ngOnInit() {
    this.getPosts();
  }

  getPosts() {

    this.postService.getTopPosts().subscribe((payload: Payload<PostResponse>) => {

      this.posts = payload.map((response: PostResponse) => { 
        return {
          id: response.id, 
          title: response.title
        };
      });

    });

  }
}

And the component HTML is:

<div *ngFor="let post of posts">
  {{post.title}}  
</div>

It is working but I would like to display "Loading" while data is loading.

Is this possible without using an extra variable on my component?

2
  • yes it can possible. show message when posts is undefined. Commented Jan 14, 2019 at 12:39
  • What is the reason of not using an 'extra' (which is not) variable ? Commented Jan 14, 2019 at 12:50

2 Answers 2

2

Not sure how to mark this as a dupe so I'm posting a link to the similar question as an answer here Angular 4 async with loading and display when empty.

You would have to update your observable to use the async pipe though so it will be something like this:

export class TopPostsComponent implements OnInit {

  posts$: Observable<PostModel[]>;

  constructor(private postService: PostService) { }

  ngOnInit() {
    this.getPosts();

    this.posts$ = this.postService.getTopPosts().pipe(
      map((payload: Payload<PostResponse>) => {
        return payload.map((response: PostResponse) => { id: response.id, title: response.title});
      })
    );
  }

}


<div *ngIf="(posts$ | async)?.length > 0; else loading">
   <ng-container *ngFor="let post of posts$ | async">
     <div>{{post.title}}</div>
   <ng-container>
</div>
<ng-template #loading>loading posts...</ng-template>
Sign up to request clarification or add additional context in comments.

Comments

0

You can not initialize posts: PostModel[] and use an <div *ngIf="!posts" >loading...</div>. Also as Osakr pointed out in the comments: set this.posts to [] because otherwise it would keep loading if the call fails.

Your new code would look like this:

export class TopPostsComponent implements OnInit {

  posts: PostModel[];

  constructor(private postService: PostService) { }

  ngOnInit() {
    this.getPosts();
  }

  getPosts() {

    this.postService.getTopPosts().subscribe((payload: Payload<PostResponse>) => {

      this.posts = payload.map((response: PostResponse) => { 
        return {
          id: response.id, 
          title: response.title
        };
      },
      error => { this.posts = [] }
      );

    });

  }
}

And the HTML is:

<div *ngIf="!posts">
  loading...
</div>
<div *ngFor="let post of posts">
  {{post.title}}  
</div>

4 Comments

What if you fail requesting the data, then posts will remain undefined and you'll have a cool spinner for the whole eternity
You can set posts to [] in the onError of the subscribe error => { this.posts = []; }
Which at the end is the same than having a isLoading variable. ( I didn't wanted to be rude, just wanted to make the creator of the post realize that having a variable for loading purposes is not bad ). Your answer is good, anyways you should add more information i guess
That's true, also a loading variable would be clearer if there are multiple people working on the same code. I'll add some more information to the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.