Code Run Through
This post follows on from posts about hybrid mobile app development using the new WordPress REST API and Ionic: Part 1, Part 2
What follows is a run through of the import parts of the code, for the application shown in Part 2.
By now you should have a [very basic] Ionic app running in your browser. The app will allow you to:
- Log into your remote, WordPress REST API enabled, website.
- Make a post from the mobile app to your WordPress site.
Pretty simple stuff.
The code that performs the magic is pretty simple too.
*I have created both an Ionic 1 and Ionic 3 repo for the App code. However, below I describe the structure for the Ionic 1 repo only.
Ionic Project Structure (Ionic 1)
As you can see from the folder structure below there are quite a few folders in our Ionic App.
However, the important files and folders are as follows:
- www/js: This folder contains all the Javascript code for the app.
- www/js/app.js: The main entry point for the app. Things like routes are configured here.
- www/js/controllers.js: The logic behind what happens on the screens is placed inside this file e.g. what should happen when the login button is pressed.
- www/js/services.js: Reusable services to perform business logic e.g. authentication and connection to WordPress
- www/templates: This folder contains the html for screen in the app.
- ionic.config.json: This file contains configuration options for the app. In Part 2, we changed a setting in this file to point to our WordPress site.
The folder structure is much like any other Angular application, so we will head straight to the code to see what the key lines are:
App.js
In app.js we configure the Angular app before it runs.
In this file we state:
- What our routes are i.e. what are the urls for our app, what html should be loaded and what Javascript files should control the html.
// Ionic uses AngularUI Router which uses the concept of states // Learn more here: https://github.com/angular-ui/ui-router // Set up the various states which the app can be in. // Each state's controller can be found in controllers.js $stateProvider .state('login', { url: '/login', templateUrl: 'templates/login.html', controller: 'LoginCtrl' }) .state('report', { url: '/report', templateUrl: 'templates/report.html', controller: 'ReportCtrl' }) // if none of the above states are matched, use this as the fallback $urlRouterProvider.otherwise('/login');
- Any injectors/interceptors we want to use. We will see later that, when we get an authentication token, we want this to be automatically passed to every subsequent HTTP call we make. An interceptor is a way of achieving this.
Controllers.js
The controllers.js file contains the logic for the Login and Report screens.
The LoginController has one function: try to login when the user clicks the Login button
$scope.login = function () { // contact our login service with the data from the username and password fields LoginService.loginUser($scope.data.username, $scope.data.password).then(function (data) { // if it is a success, go to the Report screen $state.go('report'); }, function (data) { // if there is an error pop it up onscreen var alertPopup = $ionicPopup.alert({ title: 'Login failed!', template: 'Please check your credentials!' }); }); }
The ReportController has a single function too: try to post the score and report data to WordPress (though our WordPress service).
$scope.createReport = function () { // show a saving... message while we contact the service $ionicLoading.show({ template: 'Saving...' }); // pass through the values from the score and report fields to the service WordPressService.createReport($scope.data.score, $scope.data.report).then(success, failure); }
Both controllers are very simple, it is in the Services.js where the real work is performed.
Services.js
The services.js is the work horse of the app, it contains 3x services:
- LoginService. This service is used to contact a WordPress REST API end point and request a JWT authentication token.
// the important bit, contact the end point and ask for a token $http.post('/server/wp-json/jwt-auth/v1/token', data).error(function (error) { failure(error); }).success(function (data) { // you are now logged in, save to session storage, the auth interceptor will pick up // and add to each request $window.sessionStorage.token = data.token; success(data); });
- WordPressService. The WordPress service contacts our WordPress REST Api and tries to create a post.
var data = { title: score, excerpt: report, content: report, status: 'publish' }; // the important bit, make a request to the server to create a new post // The Authentication header will be added to the request automatically by our Interceptor service $http.post('/server/wp-json/wp/v2/posts', data).error(function (error) { deferred.reject(error); }).success(function (data) { deferred.resolve(data); });
- AuthInterceptor. The interceptor service checks localstorage to see if we were given a token, if we have, then it adds it to every Http request.
request: function (config) { config.headers = config.headers || {}; //if there is a token, add it to the request if ($window.sessionStorage.token) { config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token; } return config; }
Any Questions?
That’s basically all there is to it.
If you have any questions, or any amendments that I can make to the Github repo, then please comment below….
Man this was a great tutorial I have been looking for something like this for weeks now. I am having a problem though. While I am able to sign in I can’t post to wordpress. I also have Create Post Functionality enable in JSON API my error is “jwt_auth_invalid_token” I am doing console logs everywhere but the token never seems to change. Any Help would be greatly appreciated
Hi Anne, Apologies for the late reply.
Have you added the JWT_AUTH_SECRET_KEY to your config file?
define(‘JWT_AUTH_SECRET_KEY’, ‘your-top-secrect-key’)
Also, on some servers you will need to enable http auth in your .htaccess file
“`
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) – [E=HTTP_AUTHORIZATION:%1]
“`
Hope this helps?
Conor