Home > OS >  Angular retrieve count of all posts from X-WP-Total response header while using a typed GET request
Angular retrieve count of all posts from X-WP-Total response header while using a typed GET request

Time:12-27

I am working on an Angular app that talks to Wordpress REST API. I need to fetch the count of all posts from the server. That piece of data can be obtained through the X-WP-Total response header.

I looked around the web for answers and I came across this Stack Overflow question, but it seems that most answers there focus on an untyped HttpClient.post()<any> methods. As I said, I'm working on sending a GET request to the server to fetch all posts and with that I also need to get the total count of posts. I would also like to type my requests to catch errors.

My code so far looks like this:

frontpage.component.ts:

import { Component, OnInit } from '@angular/core';
import { Question } from '../question';
import { QuestionService } from '../question.service';

@Component({
  selector: 'app-frontpage',
  templateUrl: './frontpage.component.html',
  styleUrls: ['./frontpage.component.css']
})
export class FrontpageComponent implements OnInit {

  constructor(private questionService: QuestionService) { }

  questions: Question[] = [];

  getQuestions(): void {
    this.questionService.getQuestions()
        .subscribe(questions => {
          this.questions = questions;
          console.log(questions.headers.get('X-WP-Total')); // <-- error
      
        });
  }

  ngOnInit(): void {
    this.getQuestions();
  }

}

question.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Question } from './question';

@Injectable({
  providedIn: 'root'
})
export class QuestionService {

  constructor(private http: HttpClient) { }

  /** GET all questions from the server */
  getQuestions(): Observable<Question[]> {
    return this.http.get<Question[]>("http://localhost/wordpress/wp-json/wp/v2/posts", 
      { observe: 'response'}); <-- error
  }
}

question.ts (typing interface):

export interface Question {
    "id": number;
    "date": string;
    "date_gmt": string;
    "guid": {
        "rendered": string
    };
    "modified": string;
    "modified_gmt": string;
    "slug": string;
    "status": string;
    "type": string;
    "link": string;
    "title": { 
        "rendered": string; 
    };
    "content": {
        "rendered": string;
        "protected": boolean;
    };
    "excerpt": {
        "rendered": string;
        "protected": boolean;
    };
    "author": number;
    "featured_media": number;
    "comment_status": string;
    "ping_status": string;
    "sticky": boolean;
    "template": string;
    "format": string;
    "meta": string[];
    "categories": number[];
    "tags": string[];
    "_links": {
        "self": [
            {
                "href": string;
            }
        ];
        "collection": [
            {
                "href": string;
            }
        ];
        "about": [
            {
                "href": string;
            }
        ];
        "author": [
             {
                "embeddable": boolean;
                "href": string;
            }
        ];
        "replies": [
            {
                "embeddable": boolean;
                "href": string;
            }
        ];
            "version-history": [
            {
                "count": number;
                "href": string;
            }
        ];
        "wp:attachment": [
            {
                "href": string;
            }
        ];
        "wp:term": [
            {
                "taxonomy": string;
                "embeddable": boolean;
                "href": string;
            },
            {
                "taxonomy": string;
                "embeddable": boolean;
                "href": string;
            }
        ];
        "curies": [
            {
                "name": string;
                "href": string;
                "templated": boolean;
            }
        ]
    }
}

My code runs error-free, but if I modify the QuestionService's method and add { observe: 'response'} object after the URL parameter I get the following typing error:

Type 'Observable<HttpResponse<Question[]>>' is not assignable to type 'Observable<Question[]>'.
Type 'HttpResponse<Question[]>' is missing the following properties from type 'Question[]': 
length, pop, push, concat, and 26 more.

In addition to that, in the component class file, if I try to log the header to console by simply digging it out from the questions.headers.get() method, I get the following typing error:

Property 'headers' does not exist on type 'Question[]'.

How do I proceed?

EDIT: Stackblitz here: https://stackblitz.com/edit/angular-ivy-dd5wea?

CodePudding user response:

Tell HttpClient that you want the full response with the observe option of the get() method and make the return type of method as HttpResponse.

getQuestions(): Observable<HttpResponse<Question[]>> {
    return this.http.get<Question[]>(
      'https://public-api.wordpress.com/wp/v2/sites/aleksejjj83211792.wordpress.com/posts',
      { observe: 'response' }
    );
}

In your component you can call the service method and read the header using response.headers property.

getQuestions(): void {
    this.questionService.getQuestions().subscribe((respnse) => {
      const headreValue = respnse.headers.get('X-WP-Total');
      this.questions = [...respnse.body!]
    });
}

Stackblitz Demo:- https://stackblitz.com/edit/angular-ivy-quxx7e?file=src/app/app.component.ts

References:- https://angular.io/guide/http#reading-the-full-response

  • Related