December 9, 2016
  • All
  • Ionic
  • Ionic 2
  • Tutorials
  • WordPress

The Dynamic Duo: WordPress & Ionic 2

Scott Bolinger

Scott Bolinger, the co-founder of AppPresser, has been working with mobile WordPress design and development for years. He is passionate about using WordPress in new, exciting ways and about transforming WordPress into a mobile app development platform.

Ionic and WordPress have always gone well together. Ionic’s CEO, Max Lynch, has even called Ionic “WordPress for mobile“.

WordPress makes it easy to build all kinds of websites, and Ionic makes it easy to build all kinds of mobile apps. Over 27% of the entire web is now WordPress sites, making WordPress the most popular website software by far. Ionic powers thousands of apps and is the gold standard of hybrid app development. Bringing these two technologies together is a match made in heaven.

With the final release of Ionic 2, as well as the REST API being included in WordPress core, it’s getting even easier to integrate WordPress into mobile apps.

At AppPresser, we’ve been building mobile apps with WordPress since Ionic 1 was in Alpha and the WP-API didn’t even exist. We built lots of apps with Ionic and WordPress, and we recently completely rebuilt our platform to utilize Ionic 2. We’ve learned a ton along the way, and I’m excited to share some of it with you.

How to Integrate WordPress and Ionic 2

There are a couple of different ways to get WordPress into your app, using the WP-API and iframes. Let’s look at each of these a little closer.

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.)

The WordPress REST API allows you to fetch content, as well as post data. To get this content into an Ionic 2 app, you just need to do an http request and display the content in your template. We have an example of this on our blog:

import { Component } from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

@Component({
  template: `<ion-header>
  <ion-navbar>
    <ion-title>Home</ion-title>
  </ion-navbar>
</ion-header>

<ion-content class="home">
  <ion-list>
    <button ion-item *ngFor="let item of items" (click)="itemTapped($event, item)">
    <h2 [innerHTML]="item.title.rendered"></h2>
    <p [innerHTML]="item.excerpt.rendered"></p>
    </button>
  </ion-list>
</ion-content>`;
})
export class HomePage {
    url: string = 'http://www.mysite.com/wp-json/wp/v2/posts';
    items: any;

    constructor( private http: Http ) {}

    ionViewDidEnter() {
        this.http.get( this.url )
        .map(res => res.json())
        .subscribe(data => {
          this.items = data;
        });
    }
}

Pretty straightforward, right? That code will display a list, and you just need to hook up the detail template like so:

import {NavController, NavParams} from 'ionic-angular';
import {Component} from '@angular/core';

@Component({
  template: `<ion-header>

  <ion-navbar>
    <ion-title>{{selectedItem.title.rendered}}</ion-title>
  </ion-navbar>

</ion-header>

<ion-content padding>
 <div *ngIf="selectedItem" class="selection">
    <h2 [innerHTML]="selectedItem.title.rendered"></h2>
    <div [innerHTML]="selectedItem.content.rendered"></div>
 </div>
</ion-content>
`;
})
export class PostDetail {
  selectedItem: any;

  constructor(private nav: NavController, navParams: NavParams) {
    // If we navigated to this page, we will have an item available as a nav param
    this.selectedItem = navParams.get('item');
  }

}

Now, you have a list of WordPress posts in your app.

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

  • mysite.com/wp-json/wp/v2/pages
  • mysite.com/wp-json/wp/v2/media
  • mysite.com/wp-json/wp/v2/users (requires auth)
  • mysite.com/wp-json/wp/v2/comments

You can even create a custom endpoint with any type of content you want. For example:

<?php
// add this code to a custom plugin, or child theme functions.php file
add_action( 'rest_api_init', function () {
    register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array(
        'methods' => 'GET',
        'callback' => 'my_awesome_func',
    ) );
} );

/**
 * Grab latest post title by an author!
 *
 * @param array $data Options for the function.
 * @return string|null Post title for the latest,
 * or null if none.
 */
function my_awesome_func( $data ) {
    $posts = get_posts( array(
        'author' => $data['id'],
    ) );

    if ( empty( $posts ) ) {
        return null;
    }

    return $posts[0]->post_title;
}

You could then make a request to mysite.com/myplugin/v1/author/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 other available field. Using the example template above, we could add:

<a href=“{{item.link}}”>{{item.title.rendered}}</a>
<p>{{item.date}}</p>

Grabbing some content is the easy part; what we’ve learned is that people who use WordPress like to customize everything. That’s when things get more complex.

Gotchas

The WP-API works great for displaying simple content out of the box. Doing much more than that requires quite a bit of customization.

Difficult stuff with the WP-API:

  • Posting data to WordPress, such as creating or editing a post, because it requires authentication.
  • Supporting custom plugins
  • Any interactivity, such as a form
  • Displaying custom data, like post meta

The WP-API does not display custom post types or post meta by default. That means if you have WooCommerce installed, it will not display products by default. If you add support for products, it will not display product price, images, variations, and most other product fields without custom code. You can add support for custom post types and post meta, but supporting lots of custom data gets really tedious.

Most plugins don’t support the WP-API, so you’re on your own there. Let’s say your client is using Gravity Forms, and they want their forms in the app. Doing that through the API would require rebuilding the forms in Ionic, creating custom endpoints to post data, and creating all of the http requests to send the data. You’d also have to handle sanitization, inline validation, and lots of other fun stuff.

If your client doesn’t have the budget for the hours of coding it will take you to do that, what other options are there?

iFrames FTW

Iframes are a great compromise to display custom plugin content like a form without hours of custom coding.

They have a lot of advantages, like being able to display interactive content like forms in your app easily. They have a few disadvantages, mainly that they load a bit slower and they don’t work offline. However, if we use them only where appropriate, they can be seamlessly integrated into your app.

Using Gravity Forms as an example, let’s say we have a contact form at mysite.com/contact. We can display the contact form in our Ionic app using a custom page component. Create a new component, and add this as the content:

<ion-content>
    <iframe src=“http://www.mysite.com/contact”></iframe>
</ion-content>

To make the iframe full height/width, add this to your SCSS file:

ion-content{
    iframe {
        height: 100%;
        width: 100%;
        border: none;
    }
}

Loading this page will display the whole site, so we need to remove the stuff we don’t want using a custom theme.

AppPresser uses a theme that has no header and uses Ionic styling for things like lists and page content. When you view it in the app, it looks exactly the same as any other content; you can’t even tell it’s loaded in a frame.

To achieve this, we have to switch the theme when we get a request from the app. The technical side is outside the scope of this article, but essentially we use a URL parameter on our iFrame source and switch the theme based on that. You can view the AppPresser plugin source code for a glimpse into how this works.

The final result is iFrame pages to display complex content like forms, alongside API driven lists or static content. It all works seamlessly together, thanks to Ionic.

Ionic WordPress app

API or iFrames? Both.

If you’re wondering which approach is better, the answer is both.

Use API-driven content when you can, and sprinkle in a touch of iFrames when it’s appropriate. Most popular apps use some sort of web driven content, even native apps made by Apple and Amazon. The key is to make it all work together smoothly to give your app user a great experience.

Using these two approaches side by side, powered by Ionic, we can create some amazing apps that integrate almost any type of WordPress content.

App Builder for WordPress and Ionic 2

We just launched version 3 of the AppPresser platform utilizing Ionic 2. If you’re looking for an app builder that helps you integrate WordPress into a mobile app, give us a look.

Cheers!


Scott Bolinger