WordPress Mobile Application Using WP-API & Ionic 3

Introduction

Do you want to access your WordPress site’s data through a mobile app or Make an ionic 3  WordPress Mobile Application with the WordPress Site data? Then this blog post is for you!

Ionic and WordPress have always worked great together. WordPress makes it easy and interesting to build all kinds of websites, and Ionic makes it easy to build and design all kinds of mobile apps. Getting together these technologies is a match made in heaven for developers.

In this Blog post, we will walk you through the process of creating an Ionic WordPress Mobile Application that pulls in WordPress posts and other content using the WP-API plugin. The WordPress REST API allows us to fetch content, as well as post data to our application. To get this content into an Ionic 3 app, you just need to do an http request and display the content in your template for your application.

We’ll also look at how to handle custom post types and other content using the same method we’ll use here. Once you know how to pull in posts, you can easily do the same for users, media, products, events, and lots more.

Prior to WordPress 4.7 ,you need to install the WordPress API plugin ,WP-API .For WordPress 4.7+ WP-API is integrated in the core so you don’t have to do anything.

Requirements
  • A WordPress site with a WordPress version greater or equal to 4.7.

  • An Ionic 3 App where you will communicate with the WordPress REST API(WP-API).

WP-API

As of WordPress 4.7, the REST API is a part of WordPress core. All sites updated to 4.7+ will have their content available in JSON format by default. (Sites prior to 4.7 can use the WP-API plugin).

We change the api url to get a different type of content, like pages, media, or users (requires authentication):

  • yoursite.com/wp-json/wp/v2/pages

  • yoursite.com/wp-json/wp/v2/media

  • yoursite.com/wp-json/wp/v2/users (requires auth)

  • yoursite.com/wp-json/wp/v2/comments

You could then make a request to yoursite/plugin/v1/author/id=1 and get all the posts by the author who has an ID of 1. You can also add fields to your template, like a featured image, post content, or any others. 

Now without further ado, this is what you are going to build!

Generating a new Ionic 3 Project

Lets get started by generating a new Ionic 3 project .Open your terminal on Linux/MAC and enter this :

ep10@ep10-ThinkCentre-M73:~$ ionic start wp-api-ionic blank

enter into your project folder and serve it.

ep10@ep10-ThinkCentre-M73:~$ cd wp-api-ionic
ep10@ep10-ThinkCentre-M73:~/wp-api-ionic$ ionic serve
Generating a new Provider

You’ll need a WordPress site with the WP-API (v2) active. If you are using WordPress 4.7+, you don’t need to do anything. For WordPress 4.6 and below, you will need to install and activate this plugin. You should be able to visit http://yoursite.com/wp-json/wp/v2/posts and see JSON data there.

Now generate an Ionic 3 provider to encapsulate the WordPress Rest API client logic for WordPress Mobile Application.

ep10@ep10-ThinkCentre-M73:~/wp-api-ionic$ ionic g provider wordpress 

Here we made a wp.ts file to connect to the WordPress website’s endpoint in project/src.

So project/src/wp.ts is as following.

//config constants
export const WORDPRESS_URL = 'http://www.igismap.com/';
//www.igis.com is our other website we are using as example here.
export const WORDPRESS_REST_API_URL = WORDPRESS_URL + 'wp-json/wp/v2/';

Add this wp.ts file and wordpress.ts Provider to app.module.ts file. Then now we starts with the project/src/providers/wordpress.ts.

import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import * as Wp from '../../wp'; //wp.ts file in src
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/forkJoin';

Adding imports for the wordpress.ts provider.

After we have successfully integrated the WordPress Rest API client within our Ionic 3 app ,lets now fetch WordPress posts and display in our mobile app .

In order to get a list of your recent posts you have to make an http request to the following endpoint: http://www.yoursite.com/wp-json/wp/v2/posts. This will return a JSON with the 10 latest posts of your blog in the WordPress Mobile Application.

open src/providers/wordpress.ts and lets add a method to fetch all the recent posts using the Rest client API .

@Injectable()
export class WordPressProvider {
 constructor(public http: Http){}

/////////getting recent post///////
 getRecentPosts(categoryId:number, page:number = 1){
 //if we want to query posts by category
 let category_url = categoryId? ("&categories=" + categoryId): "";
 return this.http.get(
 Wp.WORDPRESS_REST_API_URL
 + 'posts?page=' + page
 + category_url)
 .map(res => res.json());
 }

/// for getting the category list///////
 getCategory(category){
 return this.http.get(Config.WORDPRESS_REST_API_URL + "categories/" + category)
 .map(res => res.json());
 }

////////get the comments //////
 getComments(postId:number, page:number = 1){
 return this.http.get(
 Config.WORDPRESS_REST_API_URL
 + "comments?post=" + postId
 + '&page=' + page)
 .map(res => res.json());
 }

///////fething authors details///////
 getAuthor(author){
 return this.http.get(Config.WORDPRESS_REST_API_URL + "users/" + author)
 .map(res => res.json());
 }

///////getting posts by category//////
getPostCategories(post){
 let observableBatch = [];
 post.categories.forEach(category => {
 observableBatch.push(this.getCategory(category));
 });
 return Observable.forkJoin(observableBatch);
 }

Get Recent Posts

The getRecentPosts() function will return an observable with the first 10 posts that match the query written in WordPressProvider..

Now In our home.ts
we have subscribe for the observable result in order to get the posts data. Then just iterate the result data and your posts will be In WordPress Mobile Application.

So we are now opening and configuring the src/home/home.ts file.

import { PostPage } from '../post/post';
import { WordPressProvider } from '../../providers/wordpress/wordpress';
import { CommentsPage } from '../comments/comments';
import { NotificationPage } from '../notification/notification';

import { Observable } from "rxjs/Observable";
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/forkJoin';

constructor(public wordpressProvider: WordPressProvider){}

These were some imports in home.ts file.

And now the configuring the getRecentPosts() function.

 this.wordpressProvider.getRecentPosts(this.categoryId)
 .subscribe(data => {
 for(let post of data){
 post.excerpt.rendered = post.excerpt.rendered.split('<a')[0] + "</p>";
 this.posts.push(post);
 }
 loading.dismiss();
 });

In the home page the 10 recent posts are shown by the above code and the posts with some information about the title, content,published date and a link to read the full post In order to display this data we added the following code in home.html.

 <ion-card *ngFor="let post of posts" >
 <ion-title text-wrap [innerHTML]="post.title.rendered" (click)="postTapped($event, post)"></ion-title>
 <p text-wrap [innerHTML]="post.excerpt.rendered"></p>
 <a (click)="postTapped($event, post)"> Read more..</a>
 <ion-row no-padding>
 <ion-col col-6 class="date">
 <button ion-button clear small color="primary" icon-start>
 {{post.date.split('T')[0]}}
 </button>
 </ion-col>
 </ion-row>
 </ion-card>
Infinite scroll implementation

Infinite scroll is a very use full tool, It is the popular replacement for pagination technique.

As we know with the rise of social networks, the “feed” has become a popular design pattern, especially in mobile apps, which gives the idea of infinite scrolling which is loading in new items (typically older items) to the bottom of a list as the user scrolls. It has same function as pagination for limiting displayed list of data on the view.

To add infinite scroll to our ionic app we need to add the following code in our home.html file just after </ion-card>.

<ion-infinite-scroll [enabled]="morePagesAvailable" (ionInfinite)="doInfinite($event)">
 <ion-infinite-scroll-content
 loadingSpinner="bubbles"
 loadingText="Loading more posts ...">
 </ion-infinite-scroll-content>
</ion-infinite-scroll>

The next step is to initialize the morePagesAvailable variable on true when the page loads.

ionViewDidEnter() {
 this.morePagesAvailable = true;
}

As we do know WordPress api gets 10 post per page for default when we call /posts endpoint, so in order to calculate the number of pages we have to load, we are doing to focus on the doInfinite($event) function, so we are going to use some following operation now in this doInfinite($event) function.

let page = (Math.ceil(this.items.length/10)) + 1;

(Math.ceil(this.items.length/10)) here is the actual page and to get the next one we have to add +1 and the 10 is the default amount of page that is submitted here.

And here say the complete function will look like this.

// making the infinite scrolling available upto the last post of last page
 doInfinite(infiniteScroll) {
 let page = (Math.ceil(this.posts.length/10)) + 1;
 let loading = true;
//calling WordPressProvider to get recent posts by per page 
 this.wordpressProvider.getRecentPosts(this.categoryId, page)
 .subscribe(data => {
 for(let post of data){
 if(!loading){
 infiniteScroll.complete();
// infiniteScroll completed.
 }
 post.excerpt.rendered = post.excerpt.rendered.split('<a')[0] + "</p>";
 this.posts.push(post);//publishing posts
 loading = false;
 }
` }, err => {
//once we make a invalid post request which means the page is not there //and we reached the last page the below function is set to False 
//becouse there are not more pages availablle.
 this.morePagesAvailable = false;
 })
 }
Get Full Post/Post Information

When we tap on “Read More” or the Title of post from a specific post, we want to show all the details on another page. In order to achieve this, we have to pass as a parameter the post object to this new page, so in our home.ts
we create the following function.

postTapped(event, post) {
 this.navCtrl.push(PostPage, {
 item: post
 });
}

So we will create an ionic app page to show the full post and information about that.

gfgf

WordPress Post Details
  • Author

  • Content

  • Title

  • Categories

  • List of Comments

so for displaying the complete post of the home posts we create a new page i.e. post.ts
src/post/post.ts:

ionViewWillEnter(){
 this.morePagesAvailable = true;// for infiniteScroll of comments
//loading starts
 let loading = this.loadingCtrl.create();
 loading.present();

this.post = this.navParams.get('item');//gets the complete post from home

Observable.forkJoin(
 this.getAuthorData(),//provides author data
 this.getCategories(),//provides categories
 this.getComments())//provides comments
 .subscribe(data => {
 this.user = data[0].name;
 this.categories = data[1];
 this.comments = data[2];
 loading.dismiss();
 });
}

getAuthorData(){
 return this.wordpressService.getAuthor(this.post.author);
}

getCategories(){
 return this.wordpressService.getPostCategories(this.post);
}

getComments(){
 return this.wordpressService.getComments(this.post.id);
}

this post page displays a full post with the author details, categories names and comments too. The WP-API requires us to make different API call in order to get this Post details. That’s why on the previous code you can see that we have one observable per API call. All this observables are wrapped inside a forkJoin, this means that we will wait till all of them are resolved in order to continue. This is because we want to wait for all the data to be ready before displaying anything.

For the post comments list we implemented infinite scrolling. Its implementation is analogic to the implementation.

So the Html implementation of this page may look like this.

<ion-content padding>
 <ion-item *ngIf="post" class="post">
//showing posts titles and contents
 <ion-item class="post-title" [innerHTML]="post.title.rendered"></ion-item>
 <p class="post-content" [innerHTML]="post.content.rendered"></p>
 <ion-row>
 <ion-col>
//showing the date of the post published
 <ion-icon name='md-calendar'></ion-icon>
 {{post.date.split('T')[0]}}
 </ion-col>
 <ion-col text-right>
 <ion-icon name="person"></ion-icon>
 {{user}}//Author name
 </ion-col>
 </ion-row>
 <p class="bold-title">Categories:</p>
 <ion-grid>
 <ion-row>
//getting particular posts categories
 <ion-col class="category-col" *ngFor="let category of categories">
 <ion-badge (click)="goToCategoryPosts(category.id, category.name)">{{category.name}}</ion-badge>
 </ion-col>
 </ion-row>
 </ion-grid>
///comments 
 <p class="bold-title">Comments:</p>
 <ion-item *ngFor="let comment of comments">
 <ion-avatar item-start>
 <img src="{{comment.author_avatar_urls[24]}}">
 </ion-avatar>
 <h2>{{comment.author_name}}</h2>
 <p text-wrap [innerHTML]="comment.content.rendered"></p>
 </ion-item>
///infinite scroll
 <ion-infinite-scroll [enabled]="morePagesAvailable" (ionInfinite)="loadMoreComments($event)">
 <ion-infinite-scroll-content loadingSpinner="bubbles" loadingText="Loading more comments...">
 </ion-infinite-scroll-content>
 </ion-infinite-scroll>
 </ion-item>
</ion-content>t.author_name}}</h2>
 <p text-wrap [innerHTML]="comment.content.rendered"></p>
 </ion-item>
///infinite scroll
 <ion-infinite-scroll [enabled]="morePagesAvailable" (ionInfinite)="loadMoreComments($event)">
 <ion-infinite-scroll-content loadingSpinner="bubbles" loadingText="Loading more comments...">
 </ion-infinite-scroll-content>
 </ion-infinite-scroll>
 </ion-item>
</ion-content>
Get Posts by Category

In WordPress rest API we can get the posts filtered by specific category also.

On post page the categories are shown below the post’s content and to show the posts by categories we just add this in the post.ts file.

goToCategoryPosts(categoryId, categoryTitle){
 this.navCtrl.push(HomePage, {
 id: categoryId,
 title: categoryTitle
 })
 }

This goToCategoryPosts() function navigates us back to the HomePage with the selected categoryId which we tapped.

Once we reach HomePage the getRecentPosts() will be executed with the categoryId as a parameter and this will bring the latest post from the category selected and it will show the same content post as before in Homepage.

Show/Add Comments

Showing the old comments on particular post is done with the help of loadMoreComments(infiniteScroll), We Can see the comments on both home and post page. We can show a comment in a WordPress post from our ionic mobile app, with only the post Id. So the loadMoreComments(infiniteScroll) function is as follows.

 loadMoreComments(infiniteScroll) {
 let page = (this.comments.length/10) + 1;
 this.wordpressProvider.getComments(this.post.id, page)
 .subscribe(data => {
 for(let item of data){
 this.comments.push(item);
 }
 infiniteScroll.complete();
 }, err => {
 console.log(err);
 this.morePagesAvailable = false;
 })
 }

Comments also have the Infinite Scroll which loads up to the last comment on same page.

To make a comment in a WordPress post from our Ionic WordPress Mobile Application, a user must be logged in, it means that on the request we have to send the user authentication token. We have to save the token on the Native Storage, so we only need to retrieve it from there and then call the correct WP REST API endpoint.

The function to create a new comment is on post.ts file and home.ts file. There we first check if there is a logged user saved on the Native Storage. If there is a logged user on our Ionic app then we allow him to create a new comment, otherwise we show him an alert asking him to log in.

Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *