21
Feb
2019

Creating an Ionic 4 Application with WordPress Rest API – Part 1

In this post I will create a simple Ionic app that pulls from a wordpress site and displays the posts in the app. Before following the next steps make sure Node.js and npm are installed.

Install the Ionic CLI

This command will install the Ionic CLI globally on the system. The -g means it is a global install.

npm install -g ionic

Create the app

Next create the app with the ionic start command.

ionic start

Depending on the version of the Ionic CLI installed this may prompt us to continue creating an Ionic 3 application or choose the new Ionic 4 application. Choose Ionic 4.

Next give the app a name, I will call this app ‘TutorialApp’.

Next it will ask us to select a starter template. There are 3 types of templates

  • blank | A blank starter project
  • sidemenu | A starting project with a side menu with navigation in the content area
  • tabs | A starting project with a simple tabbed interface

For this tutorial we’ll choose sidemenu.

It will then prompt you to use the AppFlowSDK, say no to this.

Launch the app

cd .\TutorialApp
ionic serve - l

The -l is to launch the Ionic Lab view, which should look something like the below.

Project Structure

The ionic start command creates a project structure with a src/ directory like the following. This directory contains items such as the index.html file, configuration files for tests, an asset folder for images, and the main app/ directory for the app’s code.

Creating a WordPress Service

Before creating the service add the following import to the src/app.module.ts file.

import { HttpClientModule } from '@angular/common/http';

Then add the HttpClientModule to the @NgModule imports.

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [
    WordPressRestapiService,
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})

Now install rxjs with the following command

npm install --save rxjs

Next create a service to handle the API calls to the WordPress website which will return the data for the app.

ionic g service services/wordpress-restapi

This will create 2 new files, wordpress-restapi.service.ts and wordpress-restapi.service.spec.ts under src/app/services/.

Open the wordpress-restapi.service.ts file and update it with the following.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

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

  baseRestApiUrl: string = 'http://example.com/wp-json/wp/v2/';

  constructor(private httpClient: HttpClient) { }

  getRecentPosts(categoryId: number, page: number = 1): Observable<Post[]> {
    // Get posts by a category if a category id is passed
    let category_url = categoryId ? ("&categories=" + categoryId) : "";

    return this.httpClient.get(this.baseRestApiUrl + "posts?page=" + page + category_url).pipe(
      map((posts: Post[]) => {
        return posts.map((post) => new Post(post));
      }),
      catchError(error => {
        return Observable.throw('Something went wrong ;)');
      })
    );
  }
}

export class Post {
  author: number;
  categories: number[];
  comment_status: string;
  content: object;
  date: string;
  date_gmt: string;
  excerpt: object;
  featured_media: number;
  format: string;
  guid: object;
  id: number;
  link: string;
  meta: object;
  modified: string;
  modified_gmt: string;
  ping_status: string;
  slug: string;
  status: string;
  sticky: boolean;
  tags: number[];
  template: string;
  title: object;
  type: string;
  _links: object;

  constructor(values: Object = {}) {
    Object.assign(this, values);
  }
}

The getRecentPosts() function will retrieve the latest posts from the blog. Be sure to change the baseRestApiUrl with the live domain. We can pass a category id to get posts from a specific category or a page which will get return the next set of posts.

Displaying the posts

Update the src/app/home/home.page.ts file with the following snippet of code.

import { Component } from '@angular/core';
import { LoadingController } from '@ionic/angular';
import { WordPressRestapiService, Post } from '../services/wordpress-restapi.service';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  categoryId: number;
  private posts : Post[] = [];

  constructor(
    public loadingController: LoadingController,
    private wordpressService: WordPressRestapiService) { }

  async ngOnInit() {
    const loading = await this.loadingController.create();
    await loading.present();
    
    this.loadPosts().subscribe((posts: Post[]) => {
      this.posts = data;
      loading.dismiss();
    });
  }

  loadPosts() {
    return this.wordpressService.getRecentPosts(this.categoryId);
  }
}

The ngOnInit() will create a new loading screen to show that something is happening and to stop any user interaction while the data loads. The posts property is then updated with the data from the WordPress API.

Update the src/app/home/home.page.html file with the following snippet of code.

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-menu-button></ion-menu-button>
    </ion-buttons>
    <ion-title>
      Home
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-list>
    <ion-item *ngFor="let post of posts" (click)="openPost(post.id)">
      <ion-label [innerHTML]="post.title.rendered" text-wrap></ion-label>
      <span [innerHTML]="post.date | date:longDate" class="post-date"></span>
    </ion-item>
  </ion-list>
</ion-content>

It should now look something like the following;

Navigating to a post

First create a new page to navigate to that will display the full article.

ionic generate page Post

This command will create a new directory called post in the /src/app/ directory.

Now update /src/app/app-routing.module.ts with the following new route.

{ 
    path: 'post/:id', 
    loadChildren: './post/post.module#PostPageModule' 
}

The Router library has to be imported at the top of src/app/home/home.page.ts to be able to navigate to the post detail page.

import { Router } from '@angular/router';

Then add the following method to src/app/home/home.page.ts to open the post page

openPost(postId) {
  this.router.navigateByUrl('/post/' + postId);
}

This will open a blank page.

Displaying the post

In src/app/post/post.page.html add the following snippet.

<ion-header>
  <ion-toolbar>
    <ion-title>Post</ion-title>

    <ion-buttons slot="start">
      <ion-back-button defaultHref="/"></ion-back-button>
    </ion-buttons>

  </ion-toolbar>
</ion-header>

<ion-content padding>
  <p [innerHTML]="post.date | date:longDate"></p>
  <h1 *ngIf="post.title" [innerHTML]="post.title.rendered"></h1>
  <div *ngIf="post.content" [innerHTML]="post.content.rendered"></div>
</ion-content>

Then update the /src/app/post.page.ts file with the following.

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { LoadingController } from '@ionic/angular';
import { WordPressRestapiService, Post } from '../services/wordpress-restapi.service';

@Component({
  selector: 'app-post',
  templateUrl: './post.page.html',
  styleUrls: ['./post.page.scss'],
})
export class PostPage implements OnInit {

  id: string;
  private post: Post = new Post;

  constructor(
    public loadingController: LoadingController, 
    private route: ActivatedRoute, 
    private wordpressService: WordPressRestapiService) {}

  async ngOnInit() {

    const loading = await this.loadingController.create();
    await loading.present();

    this.id = this.route.snapshot.paramMap.get('id');

    this.getPost(this.id).subscribe((post: Post) => {
      this.post = post;
      loading.dismiss();
    });
  }

  getPost(postId) {
    return this.wordpressService.getPost(postId);
  }
}

In the wordpress-restapi.service.ts file add the following method to retrieve a single post.

  getPost(postId: number): Observable<Post> {
    return this.httpClient.get(this.baseRestApiUrl + "posts/" + postId).pipe(
      map(post => {
        return new Post(post);
      }),
      catchError(error => {
        return Observable.throw('Something went wrong ;)');
      })
    );
  }

It should start to look like the below screenshot.

In the next part I’ll look;

  • Show featured image on home page and post page.
  • Show comments on post page.
  • Show tags on post page.
  • Show categories on post page.
  • And any other additional items like infinite scroll and pull to refresh functionality.
Share

You may also like...