Siam
Siam

Reputation: 17

How to return boolean in Angular

I have a backend method called LikeExists() to verify if a certain user has liked a certain post.

public async Task<bool> LikeExists(int postId)
        {
            var post = await _postRepository.GetPostByIdAsync(postId);
            var user = await _userRepository.GetUserByUsernameAsync(User.GetUsername());

            if (_context.Likes.Where(i => i.PostId == post.Id && i.UserId == user.Id).FirstOrDefault() != null) return true;

            return false;
        }

The method works fine in Postman, but it does not do the job in Angular. If a user presses a like button I first want to check if this user has already liked this post. If he has, he will unlike it and the like will be deleted from the database. If he hasn't liked it, he will like it and the like will be saved in the database.

likeExists(){
     this.postService.likeExists(this.post.id).subscribe((response: boolean) =>{
      this.like = response;
    });
  }

  likePost() {
    if(this.likeExists){
    this.postService.likePost(this.post.id, this.model).subscribe((response: Like) => {
      this.likee = response;
      console.log(response);
      this.toastr.success('Liked');
    }, error => {
      console.log(error);
      this.toastr.error(error.error);
    });
  } else {
      this.postService.deleteLike(this.post.id).subscribe(() => {
        this.toastr.success('Unliked');
      }, error => {
        console.log(error);
      })
    }
  }

The problem is it always enters the if{} clause and never the else{} clause. The method below returns an Observable. I think the problem is that it must return a boolean. How can I make this work?

This is the method in the postService:

likeExists(postId: number) {
    return this.http.get(this.baseUrl + 'like/exists/' + postId);
  }

Upvotes: 0

Views: 185

Answers (2)

Benzara Tahar
Benzara Tahar

Reputation: 2217

Try avoiding nested subscription since it will result in an unreadable and hard to maintain code, use rxjs pipes with operators instead, try something like this:

let id= this.post.id;
let likeExists$ = this.postService.likeExists(id);

likeExists$
    .pipe(
        switchMap(likeExists => {
           if (likeExists) {
           // delete like
               return this.postService.deleteLike(id);
           }
           // otherwise addlike
               return this.postService.addLike(id);
           
        })
    ).subscribe(
       res=> this.toastr.success('Success'), 
       err=> this.toastr.error('Failed')
       );

or even shorter

let id= this.post.id;
let likeExists$ = this.postService.likeExists(id);

likeExists$
    .pipe(switchMap(
       liked => liked ? this.postService.deleteLike(id) : this.postService.addLike(id)}))
    .subscribe(
       res=> this.toastr.success('Success'), 
       err=> this.toastr.error('Failed')
       );

Upvotes: 1

Dean
Dean

Reputation: 2273

The problem is that this.http.get is asynchronous, which means that likeExists returns before this.like is being set. You need to wait for the value to be returned in your observable. Refactor your code to something along these lines:

  likePost() {
    // Check to see if like exists and wait for response from server
    this.postService.likeExists(this.post.id).subscribe((response: boolean) => {
      this.like = response;
      if (this.like) {
        this.postService.likePost(this.post.id, this.model).subscribe((response: Like) => {
          this.likee = response;
          console.log(response);
          this.toastr.success('Liked');
        }, error => {
          console.log(error);
          this.toastr.error(error.error);
        });
      } else {
        this.postService.deleteLike(this.post.id).subscribe(() => {
          this.toastr.success('Unliked');
        }, error => {
          console.log(error);
        })
      }
    });
  }

Also, this is a nice guide to asynchronous concepts in general. And the RxJS docs have a bunch of helpful information to get started.

Upvotes: 0

Related Questions