single page web apps as wordpress admin interfaces using angularjs & the wordpress rest api

26
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The WordPress REST API Josh Pollock JoshPress.net - IngotHQ.com -- CalderaWP.com

Upload: josh-pollock

Post on 13-Jan-2017

2.102 views

Category:

Internet


1 download

TRANSCRIPT

@Josh412

http://jpwp.me/ingot-admin-js

WHY?Part One

THIS IS THE NEW WAY

● WordPress is showing its age…

● This is how it catches up.

6 Changes, No Page Refresh

State Change != Page Load

Deep Linking With Router

BTW: Angular UI Router > NG Router

Probably, but don't.

Common UI/UX Pattern

● Portable● Familiar

Custom REST APIs In

WordPress● Easy● Testable● Standardized

Why Angular?● Respects standards &

separation of concerns● Relatively easy to learn● Testable● Someone else pays to

maintain it. #thanksgoogle

Why Angular?● Accessible dynamic

interfaces are not easy.● Angular ARIA is a great

start.

HOW?Part Two

Setting It Up

http://jpwp.me/ingot-admin-load

● Admin page callback prints basic HTML

● http://jpwp.me/ingot-main-page-partial● Use wp_localize_script() for:

○ Partials directory path○ Translation strings

Don't Forget To Make Your API

● Part 3 of my course● Chapter 8 of my book● My WordCamp NYC 2015 talk on

WordPress.TV

This Is A Different Talk

Angular UI Router

● What URL uses what controller and template?

● http://jpwp.me/ingot-router

ingotApp.config(function($stateProvider, $urlRouterProvider) {

$urlRouterProvider.otherwise("/");

$stateProvider

//click tests

.state('clickTests', {

url: "/click-tests",

templateUrl: INGOT_ADMIN.partials + "/click-groups.html"

})

.state('clickTests.list', {

url: "/click-tests/all",

templateUrl: INGOT_ADMIN.partials + "/list.html",

controller: 'clickGroups'

} )

.state('clickTests.edit', {

url: "/click-tests/edit/:groupID",

templateUrl: INGOT_ADMIN.partials + "/click-group.html",

controller: 'clickGroup'

} )

.state('clickTests.new', {

url: "/click-tests/new",

templateUrl: INGOT_ADMIN.partials + "/click-group.html",

controller: 'clickGroup'

} )

});

Start It Up● Include dependencies● Adding translations to

$rootScope

var ingotApp = angular.module('ingotApp', [

'ui.router',

'ui.bootstrap',

'colorpicker.module',

'ngAria',

'ngResource',

'ngclipboard',

'ngSanitize'

] )

.run( function( $rootScope, $state ) {

$rootScope.translate = INGOT_TRANSLATION;

$rootScope.partials_url = INGOT_ADMIN.partials;

}

);

Angular $http● Similar to jQuery AJAX● Use to update $scope and

$state

ingotApp.controller( 'clickDelete', ['$scope', '$http', '$stateParams', '$state', function( $scope, $http, $stateParams, $state ){

$http({

url: INGOT_ADMIN.api + 'groups/' + $stateParams.groupID + '?_wpnonce=' + INGOT_ADMIN.nonce,

method:'DELETE',

headers: {

'X-WP-Nonce': INGOT_ADMIN.nonce

}

} ).then(

function successCallback() {

swal( INGOT_TRANSLATION.deleted, "", "success" );

$scope.group = {};

$state.go('clickTests.list' );

}, function errorCallback( response ) {

var data = response.data;

var text = INGOT_TRANSLATION.sorry;

if( _.isObject( data ) && _.isDefined( data.message ) ){

text = data.message;

}

$state.go('clickTests.list' );

}

);

}]);

Factories● Reusable code for HTTP● Makes data a injected

dependency -- easily mocked/ modified

● http://jpwp.me/ingot-factory

ingotApp.factory( 'groupsFactory', function( $resource ) {

return $resource( INGOT_ADMIN.api + 'groups/:id', {

id: '@id',

_wpnonce: INGOT_ADMIN.nonce,

context: 'admin'

},{

'query' : {

transformResponse: function( data, headers ) {

var response = {

data: data,

headers: headers()

};

return response;

}

},

'update':{

method:'PUT',

headers: {

'X-WP-Nonce': INGOT_ADMIN.nonce

}

},

})

});

Factories● Think of it as your own API

client● http://jpwp.me/ingot-factory-

in-use

ingotApp.controller( 'clickGroups', ['$scope', '$http', 'groupsFactory', '$sce', function( $scope, $http, groupsFactory, $sce ) {

var page_limit = 10;

$scope.description = $sce.trustAsHtml( INGOT_TRANSLATION.descriptions.click );

groupsFactory.query( {

page: 1,

limit: page_limit,

context: 'admin',

type: 'click'

}, function ( res ) {

if ( res.data.indexOf( 'No matching' ) > -1 ) {

$scope.groups = {};

return;

};

$scope.groups = JSON.parse( res.data );

var total_groups = parseInt( res.headers[ 'x-ingot-total' ] );

var total_pages = total_groups / page_limit;

$scope.total_pages = new Array( Math.round( total_pages ) );

$scope.groups.shortcode = [];

} );

}]);

OTHER BENEFITS?

Part Three

API-Driven Plugins

● REST API Isn't a bolt on● Easier & alternative method for 3rd-party

integrations● Jump to SAAS Is Easier

Empower Others To Be

ProvidersDecentralize All The Things!

YOU?Part Four

GO DO IT!

● Angular's docs are great read them● More links, slides, examples:● JoshPress.net/wordcamp-miami-angular/

Questions?

Josh Pollock - JoshPress.net - @Josh412

Ingot - IngotHQ.com - @IngotHQ.com