Search code examples
wordpressangulartypescriptwordpress-rest-api

Filtering WordPress API with Angular pipe?


Currently trying to use a custom pipe to filter my *ngFor list items to toggle posts with a comment status of opened or closed. Seem to have run into a snag on setting it up.

Code is as follows:

app.component.html

  <select (change)="onChange($event.target.value)">
    <option value="all" selected="selected">All</option>
    <option value="open">Open</option>
    <option value="closed">Closed</option>
  </select>

  <ul>
    <li *ngFor="let post of posts | myPipe:commentStatus">
      <h1>{{ post.title.rendered }}</h1>
      comment status: {{ post.comment_status }}
    </li>
  </ul>

app.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'rest-ang';

  posts = [];

  wpUrl = 'http://wprest.local/wp-json/wp/v2/posts';

  filterByComments= '';

  //postsTitle: any = {};

  constructor(private http: HttpClient) {}

  ngOnInit(){
    return this.http.get(this.wpUrl)
      .subscribe(data => {
        for(let key in data){
          if(data.hasOwnProperty(key)){
            this.posts.push(data[key]);
          }
        }
        console.log(data);
        //console.log(this.postsTitle);
      })
  }

  onChange(optionFromMenu:string) {
    if(optionFromMenu === 'all'){
      this.posts = this.posts;
    } 
    if(optionFromMenu === 'closed') {
      this.posts = this.posts.filter(data => {
        return this.posts.includes('closed');
      });
    }
  }
}

mypipe.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'mypipe'
})
export class MyPipe implements PipeTransform {


  transform(posts: any[], comment_status: any): any {

    return posts;

    console.log(comment_status);

    if(comment_status === 'all') {


    }
  }

}

Although all my change is happening via the component.ts at the moment, I'd like to set it up in the pipe.ts file, but simply getting that working has got me a little stumped. Any suggestions appreciated.

If it helps, App was setup using Angular 6 via Angular CLI.


Solution

  • You can use template driven form way, make use of [(ngModel)] on select field & you'll no longer require that (change) method logic. So, update view code to:

    <select [(ngModel)]="commentStatus">
       <option value="all" selected="selected">All</option>
       <option value="open">Open</option>
       <option value="closed">Closed</option>
    </select>
    
    <ul>
      <li *ngFor="let post of posts | myPipe:commentStatus">
        <h1>{{ post.title }}</h1>
          comment status: {{ post.comment_status }}
      </li>
    </ul>
    

    Then update your transform method from pipe class, so that it will take current value of commentStatus variable & then filters posts array. So, the pipe code can be like:

    import { Pipe, PipeTransform } from '@angular/core';
    
    @Pipe({
      name: 'myPipe'
    })
    export class MyPipePipe implements PipeTransform {
    
      transform(posts: any[], commentStatus: any): any {
        if(!commentStatus) {
          return posts;
        }
        if(commentStatus === 'all') {
          return posts;
        } else if(commentStatus === 'open' || commentStatus === 'closed') {
          let filterdPosts =  posts.filter((i) => {
          return i.comment_status == commentStatus;
          });
          return filterdPosts;
        }
      }
    
    }
    

    Stackblitz Example