2

I am trying to create a custom pipe for getting likes on particular post, it has a service which connects to database and pull all likes related to particular post, but when i try to run in my code, i am getting return value before the getting response from service, i know i should wait for the response but not sure how to do that.. please help me resolve this issue.

HTML page

 <a [ngClass]="{'like': toggle, 'dislike': !toggle}" (click)="addremovecomment($event, mainpost)" class="float-right btn-sm text-black btn mr-1 dislike"><span><i class="fa fa-heart" style="color: dislike;"></i></span><label class="ml-1" id="lbl{{mainpost.id}}">{{mainpost | like }}</label></a>

Service

      getalllikes(post: MainPost): Observable<any> {
    return this.http.post<any>(this.baseUrl + 'GetLikes', post);
  }

Pipe

import { Pipe, PipeTransform } from '@angular/core';
import { MainPost } from '../_models';
import { LikesService } from '../_services';
import { retry } from 'rxjs/operators';

@Pipe({
  name: 'like'
})
export class LikePipe implements PipeTransform {
  postlikes = 0;
  constructor(private likeservice: LikesService) {

  }
   transform(post: MainPost, ...args: any[]): any {
    const UserId = localStorage.getItem('UserId');
    this.getlikes(post);
    if (this.postlikes === 0) {
      return '0 Likes';
      } else {
      return this.postlikes + ' Likes';
      }
  }
   getlikes(post: any) {
    this.likeservice.getalllikes(post).subscribe(data => {
      console.log();
      // likes = data;
      this.postlikes = data;
    }, (err: any) => console.error(err));

  }

}
7
  • 2
    A pipe is not a good choice for what you want. Pipes should really be pure functions. You can just async subscribe to the service directly in your template.. Commented Apr 16, 2020 at 12:26
  • @MikeOne thanks for the response, i am looping through all the posts from database, on page load i want to get how many likes are added to a particular post and also want to know if the current user have already liked the post, for the same reason i am using pipe, if not pipe please let me know what is the best approach in angular to do this Commented Apr 16, 2020 at 12:29
  • Are the likes available on the post? Commented Apr 16, 2020 at 12:33
  • yes, likes are displayed on the post(on HTML page), and in database likes are stored in different table. Commented Apr 16, 2020 at 12:34
  • Do the http call in ngOnInit() of your component and within the subscription, set the property that you bind in the template to the result of the http call. Basically move the code from your pipe to your component. Commented Apr 16, 2020 at 13:13

1 Answer 1

4

I think that it is a best practice to keep the view logic inside a pipe, you can handle the total amount of likes to each post with the help of Observables, the transform method should be returning Subject<T>:

@Pipe({
  name: 'like'
})
export class LikePipe implements PipeTransform {

  constructor(private likeService: LikeService) {} 

  transform(id: number) : Subject<Object> {
    let likeSubject = new Subject<string>();

    this.likeService.getAllLikes(id)
    .subscribe(
      (posts: number) => {
        let message = "";
        if (posts == 0)
          message = "No Likes"
        else
          message = posts.toString() + " Likes"          

        likeSubject.next(message);
    });
    return likeSubject;    
  }
}

You will have to tell angular to resolve it with the async keyword:

<span>Post1 {{ ( id | like ) | async}}</span>
<hr>
<span>Post2 {{ ( id2 | like ) | async}}</span>

Here is a full working StackBlitz app with your issue.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks the above snippet will work.It saves some time

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.