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