Ionic + WordPress

Ionic is a mobile UI framework, helping people build awesome mobile apps more easily.

It works great with WordPress as a back-end for your mobile app data, in this article we’ll build a mobile app with Ionic that uses WordPress data. This tutorial is for developers, if you are not comfortable with code, you may not get much out of it.

Ionic

ionic-logo-300

Ionic allows you to add elements to your app such as menus, page transitions, modal windows, and handle your data with pre-built “drop-in” components. It is built on AngularJS, although it abstracts much of the complexity of Angular away, and makes it easier to use. Over 600,000 apps have been built with Ionic, and they just released version 1.0 a few days ago.

Mobile apps built with Ionic can be published on iOS and Android, and more platforms are coming soon. Ionic apps are super fast, beautifully designed, and a pleasure to use.

Hybrid apps have admittedly been terrible in the past, but Ionic, along with advancements in device technology, are changing that quickly. Using a well-built Ionic app on a modern device is almost indistinguishable from a native app in many cases.

Where does WordPress come in?

wordpress-logo

WordPress is the most popular content publishing system on the web, it comprises 24% of the entire internet. Mobile apps need somewhere to store data, and WordPress is where 24% of website data lies. Using Ionic with WordPress is an important integration for any developer.

A new development in WordPress is the WP-API, which allows you to output your site content into a standardized JSON API. Since mobile apps normally use an API to get remote data, using the WP-API is a great way to get your WordPress data into a mobile app.

Let’s look at how to use the WP-API in an Ionic mobile app.

The App

What will the app look like? What can it do?

wpionic-posts

The possibilities are endless, you can add WordPress content like posts and pages, custom non-WordPress content, and app features like geolocation and push notifications. You can combine all of the great Ionic components, along with content from WordPress. Since the WP-API is a REST API, we can also create WordPress content from the app, login, and more.

We’ll focus on getting some simple WordPress content into the app, and then look at integrating some custom plugins and other data.

Project files

All of the code below is from this project file. Unzip the file, navigate to the reactorApp/www folder. There you can find the files we will edit in this tutorial.

Download project files

Quirks

Many people who are familiar with WordPress, but not familiar with the way APIs work may be surprised by what they can and cannot do.

WordPress Plugins

WordPress Plugins

Most plugins do not work out of the box. The API is just text data, it does not handle server side processing, or functionality.

Take a contact form plugin for example. It uses HTML markup, server side processing, CSS, and Javascript to work. The only thing we get through the API is the markup. To get the form to work, we would have to completely rebuild the form in the app, and make it communicate with our server via Javascript.

There are some workarounds, such as embedding an iframe with the form inside of it. This allows everything to work properly in the app.

Another example would be a podcasting plugin. We cannot use the podcast player that is on the website, but we can pull in the url of the .mp3 file from WordPress, and make our own audio player in the app.

Plugins just add content can work through the API, but many times we have to add their meta data to the API. Eventually plugin authors may add support for the API so we don’t have to do as much ourselves, but as of right now there are very few.

WordPress themes

WordPress Themes

Themes have almost nothing to do with the API, and will not be used at all in your app.

If your theme has added plugin-like functionality such as shortcodes, they will appear in your app. If it has extra features like a slider, job listings, etc, those will not work in the app. Any custom styling for layouts or colors will not translate to the app.

The WP-API gives you WordPress content, not display or functionality.

Enabling the WP-API on your site

WP API Plugin

The first thing you need is a WordPress site with the WP-API active. At the time of this writing, the WP-API is in plugin form, but it will eventually be merged into WordPress core.

Install the WP API plugin on your WordPress site. This exposes your site data, you can see it under http://mysite.com/wp-json. There are also various routes for WordPress content, such as wp-json/posts, wp-json/posts/ID or wp-json/media.

Your WordPress site data is now in a structured JSON format, it looks like this.

api-data

This is the wp-json/posts endpoint. You’ll see that it gives us the post content, author, date, excerpt, and basically everything that can be displayed on the site. What it doesn’t give us is post meta, because that requires authentication. Other endpoints, such as wp-json/users also require authentication. We’ll dig into that further down the page.

Querying the WP-API

To get data from the WP-API into your app, you’ll send an ajax GET request to one of the endpoints.

Here’s an example of a jQuery ajax call to the API.

$.ajax({
    url: 'http://url.com/wp-json/posts',
    data: {
        filter: {
        'posts_per_page': 5
        }
    },
    dataType: 'json',
    type: 'GET',
    success: function(data) {
        // success code
    },
    error: function() {
        // error code
    }
});

You’ll notice we can add filters with our request, it works much the same way as the WordPress function get_posts(). You can set categories, tags, post type, search, and more.

Here’s an example of filtering by author name and category name:

$.ajax({
    url: 'http://url.com/wp-json/posts',
    data: {
        filter: {
        'author_name': 'scott',
        'category_name': 'blog'
        }
    },
    dataType: 'json',
    type: 'GET',
    success: function(data) {
        // success code
    },
    error: function() {
        // error code
    }
});

The url string created by that function would look like this:

http://url.com/wp-json/posts?filter[author_name]=scott&filter[category_name]=blog

A full list of post filters can be found in the WP-API documentation.

Now that you know how to query the API, let’s use that in an Ionic based mobile app.

Ionic Starter Project

To kick things off, we’ll need an Ionic project to work with.

You can create an Ionic app easily using the CLI, there are instructions for that on their website. I won’t go over that again here, their instructions are great.

Let’s start with a side menu app. With the Ionic CLI tools already installed, run this command:

ionic start reactorApp sidemenu

You should have a new Ionic project called reactorApp. You can open reactorApp/www/index.html in Chrome or Safari to see what it looks like.

This starter project comes with some default pages, but we need to add content from WordPress. To do that, let’s create a new page.

Add the Posts Page

To add a new page, there are 4 things we need to do.

1. Add our visual markup (posts.html)
2. Add a menu item to access the page
3. Add a state for routing to the page
4. Optionally add a controller to execute javascript on the page

First, we need to add a page to the app for our Post list.

In reactorApp/www/templates, duplicate playlists.html and name the new file posts.html. Change everything that says “playlist” to “post.” Your new posts.html file should look like this:

<ion-view view-title="Posts">
  <ion-content>
    <ion-list>
      <ion-item ng-repeat="post in posts" href="#/app/posts/{{post.ID}}">
        {{post.title}}
      </ion-item>
    </ion-list>
  </ion-content>
</ion-view>

Next we need to add a menu item for this page. Go into reactorApp/www/templates/menu.html. Duplicate the Playlists menu item, and again change it to posts. It should look like this:

<ion-item menu-close href="#/app/playlists">
   Playlists
</ion-item>
<ion-item menu-close href="#/app/posts">
  Posts
</ion-item>

Next we need to add a state in app.js for our new page. This tells our application that this page exists, and tells it what to display. Open reactorApp/js/app.js, and copy the playlists state, then paste it directly below. Change all instances of “playlist” to “post” again. Here’s what that looks like:

  .state('app.playlists', {
      url: "/playlists",
      views: {
        'menuContent': {
          templateUrl: "templates/playlists.html",
          controller: 'PlaylistsCtrl'
        }
      }
    })

    .state('app.posts', {
      url: "/posts",
      views: {
        'menuContent': {
          templateUrl: "templates/posts.html",
          controller: 'PostsCtrl'
        }
      }
    })

You’ll notice we added this line: controller: ‘PostsCtrl’. The controller ‘controls’ what happens on that page, it’s where you’ll put your javascript functions and variables. In Angular, a controller is limited in scope to just that page, so any functions you write will only execute when that page is loaded.

In our case, the PostsCtrl is where we’ll pull in our WordPress posts.

Let’s make that controller now.

Posts Controller

Go to reactorApp/js/controllers.js, and create a new controller. Copy the PlaylistsCtrl directly underneath and call it PostsCtrl, and delete the $scope.playlists information. It should look like this:

.controller('PlaylistsCtrl', function($scope) {
  $scope.playlists = [
    { title: 'Reggae', id: 1 },
    { title: 'Chill', id: 2 },
    { title: 'Dubstep', id: 3 },
    { title: 'Indie', id: 4 },
    { title: 'Rap', id: 5 },
    { title: 'Cowbell', id: 6 }
  ];
})

.controller('PostsCtrl', function($scope) {
  // do stuff here
})

.controller('PlaylistCtrl', function($scope, $stateParams) {
});

Pay attention to the semi-colon placement, it should only be at the very end of the file.

Next, let’s add a request to our API in the PostsCtrl. First, we define our API url, along with a jsonp callback. Next, we call our API using the Angular $http.jsonp() function, which is similar to our jQuery ajax call above. We are loading our post objects into $scope.posts, which we will use in our posts.html template to display the posts.

.controller('PostsCtrl', function($scope, $http) {

  // You can change this url to experiment with other endpoints
  var postsApi = 'http://url.com/wp-json/posts?_jsonp=JSON_CALLBACK';

  // This should go in a service so we can reuse it
  $http.jsonp( postsApi ).
    success(function(data, status, headers, config) {
      $scope.posts = data;
      console.log( data );
    }).
    error(function(data, status, headers, config) {
      console.log( 'Post load error.' );
    });
  
})

At this point you can load the app in your browser, visit the Posts page by clicking the menu link, and you should see your post titles. We still can’t click through to the single post page, let’s do that next.

Single Post Pages

To add a single post page, we need to go through all of the steps we did above (minus the menu item), but make everything “post” instead of “posts.”

First, duplicate www/templates/playlist.html into a new file called post.html. Change the markup to look like this:

<ion-view view-title="{{post.title}}">
	<ion-content class="padding">
		<div ng-bind-html="content"></div>
	</ion-content>
</ion-view>

Both {{post.title}} and ng-bind-html=”content” will pull in our WordPress data. We are using ng-bind-html because we need to display raw html content. If we don’t use this, we’ll lose some data through Angular’s built in sanitization.

Next, we need to create a route and a controller for our single post page.

In www/js/app.js, add this route:

.state('app.post', {
    url: "/posts/:postId",
    views: {
      'menuContent': {
        templateUrl: "templates/post.html",
        controller: 'PostCtrl'
      }
    }
  })

In www./js/controllers.js, add this controller:

.controller('PostCtrl', function($scope, $stateParams, $sce, $http ) {

  // we get the postID from $stateParams.postId, the query the api for that post
  var singlePostApi = 'http://url.com/wp-json/posts/' + $stateParams.postId + '?_jsonp=JSON_CALLBACK';

  $http.jsonp( singlePostApi ).
    success(function(data, status, headers, config) {
      $scope.post = data;

      // must use trustAsHtml to get raw HTML from WordPress
      $scope.content = $sce.trustAsHtml(data.content);

    }).
    error(function(data, status, headers, config) {
      console.log( 'Single post load error.' );
    });

})

There’s a few things going on here. First, we are querying the WordPress API the same way we did on the posts page, but we are getting a single post instead of all the posts. We get the post ID and add that to our url, so it looks like this:

http://url.com/wp-json/posts/12?_jsonp=JSON_CALLBACK

Next, we use $sce.trustAsHtml which is an Angular service that allows us to output raw html. If we didn’t do this, we would lose some of our content.

Some of this code is redundant so it would be easier to understand. In a production app, you’d want to create a service for querying the API that is reusable, but that’s for another tutorial.

The working app

Single Post View

At this point you should have a fully working posts list and single post page. Clicking a post title on the Posts page will bring you to the single post view.

There is still a lot more we can do with this app, such as pull to refresh, infinite scroll, adding support for custom plugins, login authentication, etc. In future articles we will look at adding more custom functionality to your app.

Category:
Tutorial
Tags:

Join the conversation! 28 Comments

  1. Hi Scott, great article, but how do you get your restful api into ionic without the html tags i.e tags etc?

    Reply
    • Hi Rob, the wp-api outputs html, so there is no way to strip the tags. I’m not sure why you’d want to do that?

      Reply
      • For example Scott, the API currently gives me example:

        This is my post example (with P tags etc)

        but i would want to display the information as

        “This is my post example” (without the p tags)

        Any ideas?

        Reply
  2. Hi Scott, I am interested on how you got the api into the app, without the html tags tags etc, can you elaborate on this?

    Thanks

    Reply
  3. Thanks for this post! It’s really helping me understand how Ionic + JSON + WordPress work together.

    One question… I would assume pulling in WP Page content could be done using the Single Post Pages example here, but it’s not working for me. Any advice on how to pull in content from specific WP pages?

    Reply
  4. How about push notification? Could you implement it?
    I use may plugin but could not work

    Reply
    • Push notifications can be implemented any number of ways. Our service has push notifications built-in, you could also use Ionic Push, AWS, and many others.

      Reply
  5. Hi Scott, it’s very helpful article,
    but I get some problem here.

    In ionic serve, I get the JSON parsed correctly,
    but when it’s run in the android, there’s nothing there 🙁

    Any idea?

    Reply
  6. I build this application in android. But in post section nothing is loaded post section is blank. when I execute ionic serve in google chrome everything is working and post is displayed.

    Reply
  7. Very nice work Scoot, but in the example from above there are images of post. How can i insert this to my post list? thank you advanced.

    Reply
  8. Hi i downloaded the project and added an android platform to it.
    After i run build, the app works on android device but the posts don’t show..it comes up blank.
    Ive had similar problems with my own app..
    runs perfectly in browser but when deployed to device the posts dont show up..
    Almost as though the controller directive isn’t running

    pls if anyone can help on this i would be greatly indebted

    Reply
  9. Trying to pull the featured_image but I get just the text, how do I get the actual image?

    Reply
  10. hi.. i wanted to implement an infinite scroll on this and i dont know how to go about it..
    ive read on infinite scroll but i can implement it as my app just pulls the recent 10 posts.

    an example code would be nice
    thanks.

    Reply
  11. jonsem u have to do this: {{ post.featured_image.source }} to set featured_image

    Reply
  12. Hi scott great tutorial!! I want to put the category’s post in a single post i do this: {{ post.terms.category.name }} but the category doesn’t appear? Do you have an issue?

    Reply
  13. Has anyone implements infinite scroll i try but not work

    Reply
  14. I not have knowledge modifying controller, can someone help me embeding into wp post gallery?
    here the script:
    http://codepen.io/ionic/pen/nxEdH
    thanks in advance,

    Reply
  15. Thanks so much Scott! fabulous tutorial. Would love your thoughts on how I capture an email address in my app, store to my WP database, and then return to the app user a QR code?? 🙂

    Reply
  16. Hi,

    i tried to to do your tutorial but i get a “Single post load error”.
    $stateParams.postId = undefiend

    console log shows this: undefined?_jsonp=JSON_CALLBACK”

    pls if anyone can help on this i would be great

    Reply
  17. How can I take the URL of the featured image ?

    I have tried it with this code, but I get all the images without order (they appear in a different order than articles):

    $http.get(url)
    .success(function(response){

    angular.forEach(response, function(child){

    $http.get(urlMedia+child.featured_image)
    .success(function(data){
    $scope.imgs.push(data.source_url);
    });

    $scope.posts.push(child);

    });

    })
    .error(function(response, status){
    console.log(“Error while received response. ” + status + response);
    });

    How can I solve that ? Do you know a better way ?

    Reply
  18. hi,
    thanks for useful guide. I tried to run this application on real device but it was not shows the posts content on post menu opening. I tried in several devices with several version of androids. but the same result, however it works fine with “ionic serve” command.

    Reply
  19. Hello , Thanks so much for this toturial , i just one problem , this is not fast , it work slow , how can i make it fast ?

    Reply

Leave a Reply

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