I am working on an Angular app (similar to how Stack Overflow works) that displays posts (or questions if you will) and other related data from Wordpress REST API. What I am trying to accomplish is to have a running number in the URL e.g. http://localhost:4200/frontpage/:pagenumber
and have that reflect the content on the site. I have successfully created an app in which users can click on pagination control buttons to navigate between pages (while running the same component the whole time), but the content on the web page does not update with that and that is what I need to fix. So, say the user navigates to http://localhost:4200/frontpage/2
the app should fire a function call that sends a GET
request to Wordpress REST API: /wp/v2/posts?page=2&per_page=3
and the resulting data should be reflected with that action.
I am also experiencing an issue where the page count header X-WP-TotalPages
returned by the API gives me a page count lower than the actual page count of the site. My Wordpress site has 6 public posts but X-WP-TotalPages
returns a value of 1
when limiting the result set to 3 posts per_page
. What gives?
You will find my Stackblitz here: https://stackblitz.com/edit/angular-ivy-wqptx4?file=src/app/frontpage/frontpage.component.ts
Here are the important parts:
app-routing.module.ts:
const routes: Routes = [
{ path: 'frontpage/:page', component: FrontpageComponent },
{ path: '', redirectTo: '/frontpage/1', pathMatch: 'full' },
];
question.service.ts:
/** GET all questions */
getQuestions(page: number): Observable<Question[]> {
return this.http.get<Question[]>(
`https://public-api.wordpress.com/wp/v2/sites/aleksejjj83211792.wordpress.com/posts?page=${page}&per_page=3`
);
}
/** GET headers from response with the 'observe' option */
getHeaders(): Observable<HttpResponse<Question[]>> {
return this.http.get<Question[]>(
'https://public-api.wordpress.com/wp/v2/sites/aleksejjj83211792.wordpress.com/posts', { observe: 'response' }
);
}
frontpage.component.html:
<!-- A row of pagination control buttons -->
<nav aria-label="Page navigation example">
<ul class="pagination">
<li *ngFor="let page of [].constructor(pageCount); let i = index" class="page-item">
<a routerLink="/frontpage/{{ i + 1 }}" class="page-link" href="#">{{ i + 1 }}</a>
</li>
</ul>
</nav>
frontpage.component.ts:
export class FrontpageComponent implements OnInit {
constructor(
private questionService: QuestionService,
private router: Router,
private route: ActivatedRoute
) {
router.events
.pipe(filter((event) => event instanceof NavigationEnd))
.subscribe((event: NavigationEnd) => {
const splitURL = event.url.split('/');
console.log('navigated to ', event.url);
this.getQuestions(+splitURL[2]);
});
}
getQuestionCount(): void {
this.questionService.getHeaders().subscribe((questions) => {
this.pageCount = +questions.headers.get('X-WP-TotalPages');
console.log('pageCount', this.pageCount);
});
ngOnInit(): void {
this.getQuestionCount();
const pageParam = +this.route.snapshot.paramMap.get('page');
this.mergedArray$ = this.getQuestions(pageParam);
}
}
I realized that if I manually go to the browser's address bar, type in a page number and hit Enter key the content on the site actually does update according to the page number, but pressing the pagination control button at the bottom of the page does nothing, so I need to fix that.
There is a minor mistake in getHeaders
within QuestionService
. When you call /posts
without a parameter how many items you wish to have per page wordpress will apply a default pageSize - and use that default to calculate the total pages.
So easily adding the pageSize to the call does the trick.
Change it like that:
getHeaders(): Observable<HttpResponse<Question[]>> {
return this.http.get<Question[]>(
'https://public-api.wordpress.com/wp/v2/sites/aleksejjj83211792.wordpress.com/posts?per_page=3',
{ observe: 'response' }
);
}