SlideShare a Scribd company logo
1 of 73
Single Page Applications In
WordPress Built With AngularJS
And The WP REST API
by Ken Schnetz
Introduction
Welcome to WordCamp Sacramento, 2018!
Definitions
Why Single Page Applications?
Building a SPA Theme for WordPress
Definitions
Single Page Application (SPA)
A website with a single page
The most basic SPA consists of an
index.html and bundle of CSS/HTML/JS
files
SPA’s transfer the rendering of content
from the server to the browser
No page refresh: feels like a mobile
app
Definitions
Single Page Application (SPA)
SPA’s provide two way data binding
var source = "docs.angularjs.org/guide/concepts"
Definitions
AngularJS
Google’s JavaScript structural
framework
Extends HTML syntax to seamlessly bind
with the app JS
A client side solution to building
SPA’s
Best used with API’s
var source = "docs.angularjs.org"
Definitions
WordPress REST API
Proof that WordPress is embracing the
concept of front-end applications
The WP REST API consists of easy-to-use
HTTP endpoints
Allow dynamic population of front-end
applications with any WordPress data
Fastest way to access WordPress data in
JSON format
Definitions
WordPress REST API
The WP REST API can be extended to:
Modify responses
Create internal classes
Add endpoints
Access custom post types/taxonomies
So much more…
var source = "developer.wordpress.org/rest-api"
Why Single Page Applications?
Advantages
Incredibly lightweight
Rapid deployment
Extremely modular
Built in mock testing
Why Single Page Applications?
Challenges
Not suited for games, GUI editors, or
non-standard DOM manipulation
Initial load time
Extra effort required for SEO
Why Single Page Applications?
SPA’s are how sites of the future will
be built. It’s already happening:
var source = "madewithangular.com"
Building a SPA Theme for
WordPress
Creating a WordPress theme for the SPA
Understanding AngularJS SPA components
Building an AngularJS SPA
Leveraging the WP REST API
Creating a WordPress theme for the
SPA
Folder structure
root/
includes
assets/
app…
img
lib/
css
js
Creating a WordPress theme for the
SPA
File structure
root/
footer.php
functions.php
header.php
index.php
style.css
Creating a WordPress theme for the
SPA
File structure
root/includes/
enqueue.php
Creating a WordPress theme for the
SPA
File structure
root/assets/lib/css/
bootstrap.min.css
sizer.css
Creating a WordPress theme for the
SPA
File structure
root/assets/lib/js/
angular.min.js
angular-sanitize.min.js
bootstrap.min.js
jquery.min.js
ui-route.min.js
Creating a WordPress theme for the
SPA
functions.php
<?php
/*
* Author: Kenneth Schnetz, VendorFuel
* URL:vendorfuel.com/spa-theme
* Custom functions, support, custom post types and more.
*/
require_once 'includes/enqueue.php’;
add_filter('redirect_canonical', 'no_redirect');
function no_redirect () {
return false;
}
?>
Creating a WordPress theme for the
SPA
header.php
<!doctype html>
<html class="m-t-0" ng-app="spaApp" resize ng-cloak>
<head>
<base href="/">
<title ng-bind="$root.title">SPA Theme</title>
<link href="<?php echo get_template_directory_uri();
?>/assets/img/icons/favicon.ico" rel="shortcut icon">
<link href="<?php echo get_template_directory_uri();
?>/assets/img/icons/touch.png" rel="apple-touch-icon-precomposed">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<?php wp_head(); ?>
</head>
<body>
<div ui-view="header"></div
Creating a WordPress theme for the
SPA
index.php
<?php get_header(); ?>
<div id="content" class="container-fluid" style="height:calc(100vh–
55px);">
<div class="container">
<div ui-view></div>
</div>
</div>
<?php get_footer(); ?>
Creating a WordPress theme for the
SPA
footer.php
<div ui-view="footer"></div>
</body>
</html>
Creating a WordPress theme for the
SPA
style.css
/*
* Theme Name: SPA Theme
* Theme URI: http://vendorfuel.com
* Description: SPA Theme for WordPress
* Version: 1.0.0
* Author: Ken Schnetz
* Author URI: http://vendorfuel.com
* Tags: AngularJS, Single Page Application, HTML5, CSS3
*/
.active { font-weight: bold; }
.card { box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); transition: 0.3s; }
.card:hover { box-shadow: 0 10px 20px 0 rgba(0,0,0,0.2); }
Creating a WordPress theme for the
SPA
Enqueueing files
Enqueue theme files to allow theme
activation
Library scripts
App scripts
Library styles
Localized variables
NOTE: minify app scripts in
production
Creating a WordPress theme for the
SPA
enqueue.php
<?php
add_action('wp_enqueue_scripts', 'load_assets’);
function load_assets() {
//lib scripts
wp_enqueue_script( 'jquery', get_template_directory_uri() .
'/assets/lib/js/jquery.min.js’);
wp_enqueue_script( 'bootstrap', get_template_directory_uri() .
'/assets/lib/js/bootstrap.min.js’);
wp_enqueue_script( 'angular', get_template_directory_uri() .
'/assets/lib/js/angular.min.js’);
wp_enqueue_script( 'angular-router', get_template_directory_uri() .
'/assets/lib/js/ui-route.min.js’);
wp_enqueue_script( 'angular-sanitize', get_template_directory_uri() .
'/assets/lib/js/angular-sanitize.min.js');
Creating a WordPress theme for the
SPA
enqueue.php
//app scripts: ctrl–controller, dir-directive, fac–factory, fil-filter,
svc-service
wp_enqueue_script( 'app', get_template_directory_uri() . '/assets/app/app.js’);
wp_enqueue_script( 'app-config', get_template_directory_uri() . '/assets/app/config.js’);
wp_enqueue_script( 'app-run', get_template_directory_uri() . '/assets/app/run.js’);
wp_enqueue_script( 'fac-intc', get_template_directory_uri() . '/assets/app/factories/interceptor.js’);
wp_enqueue_script( 'svc-post', get_template_directory_uri() . '/assets/app/services/post.js’);
wp_enqueue_script( 'svc-page', get_template_directory_uri() . '/assets/app/services/page.js’);
wp_enqueue_script( 'dir-resize', get_template_directory_uri() . '/assets/app/directives/resize.js’);
wp_enqueue_script( 'ctrl-header', get_template_directory_uri() . '/assets/app/controllers/header.js’);
wp_enqueue_script( 'ctrl-home', get_template_directory_uri() . '/assets/app/controllers/home.js’);
wp_enqueue_script( 'ctrl-contact', get_template_directory_uri() . '/assets/app/controllers/contact.js’);
wp_enqueue_script( 'ctrl-post', get_template_directory_uri() . '/assets/app/controllers/post.js’);
wp_enqueue_script( 'ctrl-footer', get_template_directory_uri() . '/assets/app/controllers/footer.js’);
//NOTE: these should all be concatenated, minified, and enqueued as one
file in production
Creating a WordPress theme for the
SPA
enqueue.php
//styles
wp_enqueue_style( 'bootstrap', get_template_directory_uri() .
'/assets/lib/css/bootstrap.min.css’);
wp_enqueue_style( 'sizer', get_template_directory_uri() .
'/assets/lib/css/sizer.css’);
wp_enqueue_style( 'styles', get_template_directory_uri() . '/style.css');
Creating a WordPress theme for the
SPA
enqueue.php
//WordPress variables to be used in SPA
wp_localize_script('app', 'localized', array(
'dir' => array(
'url' => get_home_url(),
'root' => get_template_directory_uri(),
'templates' => get_template_directory_uri() .
'/assets/app/templates/'
),
'nonce' => wp_create_nonce( 'wp_rest' )
)
);
}
?>
Building an AngularJS SPA
Understanding the components
View: a rendered state of the application
State: different parts or “pages” of the site
Template: HTML file associated with a
specific view
Model: the data associated with the
application
Scope: context where the model is stored and
accessed
Controller: main logic behind each specific
view
Building an AngularJS SPA
Understanding the components
Expression: code snippets in HTML to access
scope data
Directive: HTML extensions with custom
attributes and elements
Filter: formats the value of an expression
Factory/Service: reusable logic accessible to
all controllers
Module: container for the different parts of
the app
Building an AngularJS SPA
Folder structure
root/assets/app/
controllers
directives
factories
filters
services
templates
Building an AngularJS SPA
Base app files
root/assets/app/
app.js
config.js
run.js
Building an AngularJS SPA
Base app files - app.js
Main Module that defines the entire
application
Minimal amount of code
Dependency injection
Building an AngularJS SPA
Base app files - app.js
(function () { 'use strict'; }());
var admin_js_app = admin_js_app || {};
admin_js_app.app = angular.module('spaApp', ['ui.router', 'ngSanitize']);
Building an AngularJS SPA
Base app files - config.js
App configuration file
SPA routing and URL settings
Defining an HTTP interceptor
Building an AngularJS SPA
Base app files - config.js
admin_js_app.app.config(['$stateProvider', '$urlRouterProvider',
'$httpProvider', '$provide', '$locationProvider',
function($stateProvider, $urlRouterProvider, $httpProvider, $provide,
$locationProvider) {
$locationProvider.hashPrefix('');
$locationProvider.html5Mode({ enabled: true });
$urlRouterProvider.otherwise('/');
Building an AngularJS SPA
Base app files - config.js
$stateProvider.state('root', {
views: {
'header': {
templateUrl: localized.dir.templates + '/header.html',
controller:'HeaderController'
},
'footer': {
templateUrl: localized.dir.templates + '/footer.html',
controller:'FooterController'
}
}
})
Building an AngularJS SPA
Base app files - config.js
.state('home', {
parent: 'root', url: '/', views: {
'@': {
templateUrl: localized.dir.templates + 'home.html',
controller: 'HomeController'
}
}
})
Building an AngularJS SPA
Base app files - config.js
.state('contact', {
parent: 'root', url: '/contact', views: {
'@': {
templateUrl: localized.dir.templates + 'contact.html',
controller: 'ContactController'
}
}
})
Building an AngularJS SPA
Base app files - config.js
.state('post', {
parent: 'root', url: '/post', views: {
'@': {
templateUrl: localized.dir.templates + 'post.html',
controller: 'PostController'
}
}
})
Building an AngularJS SPA
Base app files - config.js
$httpProvider.interceptors.push('interceptor’);
}]);
Building an AngularJS SPA
Base app files - run.js
App initialization
Global scope (rootScope)
Perfect for storing localized variables
in the model
Building an AngularJS SPA
Base app files - run.js
admin_js_app.app.run(function($rootScope){
$rootScope.rootPath = localized.dir.root;
$rootScope.page = 0;
$rootScope.title = "SPA Theme";
});
Building an AngularJS SPA
Views
Controller
Template
Together make up a view
Building an AngularJS SPA
Views: header - controller
admin_js_app.app.controller('HeaderController', function($rootScope,
$scope, $http) {
jQuery('.navbar-collapse .nav a').on('click', function(){
if(jQuery('.navbar-collapse').hasClass('in')) {
jQuery(".navbar-collapse").collapse('hide’);
}
});
});
Building an AngularJS SPA
Views: header - template
<div id="navigation" class="col-xs-12 p-0">
<nav class="navbar navbar-default m-0">
<div class="container p-0">
<div class="col-xs-12">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-
toggle="collapse" data-target="#myNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a ui-sref="home"><img class="h-80" ng-
src="{{rootPath}}/assets/img/brand.png"></a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav navbar-right p-tb-15">
<li><a ui-sref="home" ng-class="page == 1 ? 'active’ :
''">Home</a></li>
<li><a ui-sref="contact" ng-class="page == 2 ? 'active’ :
'">Contact</a></li>
</ul>
</div>
</div>
</div>
</nav>
</div>
Building an AngularJS SPA
Views: header
Building an AngularJS SPA
Views: home - controller
admin_js_app.app.controller('HomeController', function($rootScope,
$scope, Post) {
$rootScope.page = 1;
$scope.loading = true;
$rootScope.title = "SPA Theme - Home";
$scope.posts = {};
Post.GetRecent().then(function(p) {
if (!p.error) {
$scope.posts = p;
}
$scope.loading = false;
});
});
Building an AngularJS SPA
Views: home - template
<div class="col-xs-12 p-0">
<div ng-if="loading" class="col-xs-12 p-0 m-tb-40 text-center">
<img class="h-100" ng-src="{{imagePath}}/loading.gif">
</div>
<div ng-if="!loading" ng-repeat="post in posts track by $index" class="col-
xs-12 col-md-4 m-t-20 p-0">
<a ng-if="posts" ui-sref="post({ slug:post.slug })">
<div class="col-xs-12 p-20 card">
<div class="col-xs-12 p-0">
<img class="wp-100" ng-src="{{post.thumbnail_url || rootPath +
'/assets/img/placeholder.png'}}">
</div>
<div class="col-xs-12 p-s-0 p-t-20">
<div class="col-xs-12 p-s-0">
<span class="pull-left"><span ng-bind-html="post.date | date :
'longDate'"></span></span>
<span class="pull-right"><span ng-bind-
html="post.author"></span></span>
</div>
<hr class="col-xs-12 p-0">
<div class="col-xs-12 p-0">
<h2 class="text-center m-t-0" ng-bind-html="post.title"></h2>
<span ng-bind-html="post.excerpt"></span>
</div>
</div>
</div>
</a>
</div>
</div>
Building an AngularJS SPA
Views: home
Building an AngularJS SPA
Views: footer - controller
admin_js_app.app.controller('FooterController', function($rootScope,
$scope) {});
Building an AngularJS SPA
Views: footer - template
<div class="col-xs-12 p-0">
<footer id="footer" class="navbar navbar-default m-0">
<div class="container p-20 text-center">
&copy; 2018 Copyright VendorFuel
</div>
</footer>
</div>
Building an AngularJS SPA
Views: footer
Building an AngularJS SPA
Views: header, home, footer combined
Building an AngularJS SPA
Directives
Extended HTML attributes with the ng- prefix
Many built in directives
ng-app
ng-model
ng-bind
etc…
You can define your own directives
Resize: get current screen width in
relation to bootstrap columns (xs, sm, md,
lg)
Building an AngularJS SPA
Directives - resize
admin_js_app.app.directive('resize', function($window) {
return function($scope) {
GetSizing();
angular.element($window).bind('resize', function() {
$scope.$apply(function() {
GetSizing();
});
});
function GetSizing() {
$scope.width = $window.innerWidth;
CheckSizing($scope.width);
};
function CheckSizing(w) {
if (w < 768) { SetBools(true); }
else if ((w >= 768) && (w < 992)) { SetBools(false, true); }
else if ((w >= 992) && (w < 1200)) { SetBools(false, false, true);}
else { SetBools(false, false, false, true); }
};
function SetBools(xs = false, sm = false, md = false, lg = false) {
$scope.isXS = xs; $scope.isSM = sm; $scope.isMD = md; $scope.isLG = lg;
};
};
});
Building an AngularJS SPA
Factories
Global functionality provided to the
controllers
Provides modularized global
functionality
You can define your own factories
Interceptor: modify HTTP requests and
responses
Building an AngularJS SPA
Factories - interceptor
admin_js_app.app.factory('interceptor', ['$q', function($q) {
return {
request: function(config) {
config.headers['X-WP-Nonce'] = localized.nonce;
return config || $q.when(config);
},
requestError: function(rejection) {
return $q.reject(rejection);
},
response: function(response) {
return response || $q.when(response);
},
responseError: function(rejection) {
return $q.reject(rejection);
}
};
}]);
Building an AngularJS SPA
Services
Similar to factories
Provides modularized global functionality
Many built in services:
$http
$location
$timeout
etc…
You can define your own services
Leveraging the WP REST API is a perfect use case
Leveraging the WP REST API
Provides API endpoints for WordPress
data types
Sends and receives JSON objects
Extremely simple to use
NOTE: you will need a localized nonce
to utilize the WP REST API fully from a
SPA
Leveraging the WP REST API
Use case examples
yoursite.com/wp-json/v2/
pages
pages?slug=spa-contact
posts
posts?id=1
Will not have linked data
posts?_embed&id=1
Will have linked data
Leveraging the WP REST API
Page
Page with a contact form via shortcode
Page service
Page controller
Page template
Leveraging the WP REST API
Page - content
WordPress page content in this example:
<h3 style="text-align: center;">
Please fill out your contact info and we will get back to you
shortly!
</h3>
<div style="text-align: center;">
[contact-form-7 id="5" title="Contact form 1"]
</div>
Leveraging the WP REST API
Page - service
admin_js_app.app.service('Page', function($rootScope, $http, $sce) {
this.GetSlug = function (slug) {
var req = { method: 'GET', url: localized.dir.url + '/wp-
json/wp/v2/pages?slug=' + slug };
var promise = $http(req).then(function(resp){
var page = {};
if (resp.data[0]) {
page.id = resp.data[0].id;
page.title = $sce.trustAsHtml(resp.data[0].title.rendered);
page.content = $sce.trustAsHtml(resp.data[0].content.rendered);
} else { page.error = "Page not found"; }
return page;
}, function(resp){ return resp; });
return promise;
}
});
Leveraging the WP REST API
Page - controller
admin_js_app.app.controller('ContactController', function($rootScope,
$scope, Page) {
$rootScope.page = 2;
$scope.loading = true;
$rootScope.title = "SPA Theme - Contact";
Page.GetSlug("contact").then(function(p) {
if (p.error) {
$scope.pageTitle = p.error;
} else {
$scope.pageTitle = p.title;
$scope.pageContent = p.content;
}
$scope.loading = false;
});
});
Leveraging the WP REST API
Page - template
<div ng-if="loading" class="col-xs-12 p-0 m-tb-40 text-center">
<img class="h-100" ng-src="{{imagePath}}/loading.gif">
</div>
<div ng-if="!loading" class="col-xs-12 p-0 m-tb-40">
<h1 ng-bind="pageTitle"></h1>
<hr class="col-xs-12">
<div class="col-xs-12" ng-bind-html="pageContent"></div>
</div>
Leveraging the WP REST API
Page - view
Leveraging the WP REST API
Post
Post with content
For this example: hello-world
Post service
Post controller
Post template
Leveraging the WP REST API
Post – service
admin_js_app.app.service('Post', function($rootScope, $http, $sce) {
this.GetSlug = function (slug) {
var req = { method: 'GET', url: localized.dir.url + '/wp-
json/wp/v2/posts?_embed&slug=' + slug };
var promise = $http(req).then(function(resp){
var post = resp.data[0];
var tempPost = {};
if (post) {
tempPost = { id: post.id,
slug: post.slug,
date: FormatDate(post.date),
author: post._embedded.author[0].name,
title: $sce.trustAsHtml(post.title.rendered),
excerpt: $sce.trustAsHtml(post.excerpt.rendered),
content: $sce.trustAsHtml(post.content.rendered) };
} else { tempPost.error = "Post not found"; }
return tempPost;
}, function(resp){ return resp; });
return promise;
};
Leveraging the WP REST API
Post – service
this.GetRecent = function (count = 6) {
var req = { method: 'GET', url: localized.dir.url + '/wp-
json/wp/v2/posts?_embed&per_page=' + count };
var promise = $http(req).then(function(resp){
var posts = [];
var tempPost = {};
if (resp.data) {
angular.forEach(resp.data, function(value) {
tempPost = { id: value.id,
slug: value.slug,
date: FormatDate(value.date),
author: value._embedded.author[0].name,
title: $sce.trustAsHtml(value.title.rendered),
excerpt: $sce.trustAsHtml(value.excerpt.rendered),
content: $sce.trustAsHtml(value.content.rendered)};
posts.push(tempPost);
});
return posts.reverse();
} else { post.error = "Post not found"; }
return post;
}, function(resp){ return resp; });
return promise;
};
Leveraging the WP REST API
Post – service
function FormatDate(d) {
var months = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];
var dt = new Date(d);
return months[dt.getMonth()] + " " + dt.getDate() + ", " +
dt.getFullYear();
};
});
Leveraging the WP REST API
Post – controller
admin_js_app.app.controller('PostController', function($rootScope,
$scope, $stateParams, Post) {
$rootScope.page = 0;
$scope.loading = true;
$scope.slug = $stateParams.slug;
$rootScope.title = "SPA Theme - " + $scope.slug;
$scope.post = {};
Post.GetSlug($scope.slug).then(function(p) {
$scope.post.error = false;
if (p.error) {
$scope.post.title = p.error;
$scope.post.error = true;
} else {
$scope.post = p;
}
$scope.loading = false;
});
});
Leveraging the WP REST API
Post – template
<div ng-if="loading" class="col-xs-12 p-0 m-tb-40 text-center">
<img class="h-100" ng-src="{{imagePath}}/loading.gif">
</div>
<div ng-if="!loading" class="col-xs-12 p-0 m-tb-40">
<h1 ng-bind="post.title"></h1>
<hr class="col-xs-12 p-0">
<span ng-bind="post.date" class="pull-left"></span>
<span ng-bind="post.author" class="pull-right"></span>
<hr ng-if=“!post.error" class="col-xs-12 p-0">
<div class="col-xs-12 p-0" ng-bind-html="post.content"></div>
</div>
Leveraging the WP REST API
Post – view
Conclusion
SPA examples and FREE SPA theme source
code – see me in the lobby!
Thank you for stopping by.

More Related Content

Recently uploaded

CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Recently uploaded (20)

Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 

Featured

Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
 
Good Stuff Happens in 1:1 Meetings: Why you need them and how to do them well
Good Stuff Happens in 1:1 Meetings: Why you need them and how to do them wellGood Stuff Happens in 1:1 Meetings: Why you need them and how to do them well
Good Stuff Happens in 1:1 Meetings: Why you need them and how to do them well
Saba Software
 
Introduction to C Programming Language
Introduction to C Programming LanguageIntroduction to C Programming Language
Introduction to C Programming Language
Simplilearn
 

Featured (20)

How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
 
12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work
 
ChatGPT webinar slides
ChatGPT webinar slidesChatGPT webinar slides
ChatGPT webinar slides
 
More than Just Lines on a Map: Best Practices for U.S Bike Routes
More than Just Lines on a Map: Best Practices for U.S Bike RoutesMore than Just Lines on a Map: Best Practices for U.S Bike Routes
More than Just Lines on a Map: Best Practices for U.S Bike Routes
 
Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G...
Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G...Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G...
Ride the Storm: Navigating Through Unstable Periods / Katerina Rudko (Belka G...
 
Barbie - Brand Strategy Presentation
Barbie - Brand Strategy PresentationBarbie - Brand Strategy Presentation
Barbie - Brand Strategy Presentation
 
Good Stuff Happens in 1:1 Meetings: Why you need them and how to do them well
Good Stuff Happens in 1:1 Meetings: Why you need them and how to do them wellGood Stuff Happens in 1:1 Meetings: Why you need them and how to do them well
Good Stuff Happens in 1:1 Meetings: Why you need them and how to do them well
 
Introduction to C Programming Language
Introduction to C Programming LanguageIntroduction to C Programming Language
Introduction to C Programming Language
 

Single page applications in word press built with angular js and the wp rest api

  • 1. Single Page Applications In WordPress Built With AngularJS And The WP REST API by Ken Schnetz
  • 2. Introduction Welcome to WordCamp Sacramento, 2018! Definitions Why Single Page Applications? Building a SPA Theme for WordPress
  • 3. Definitions Single Page Application (SPA) A website with a single page The most basic SPA consists of an index.html and bundle of CSS/HTML/JS files SPA’s transfer the rendering of content from the server to the browser No page refresh: feels like a mobile app
  • 4. Definitions Single Page Application (SPA) SPA’s provide two way data binding var source = "docs.angularjs.org/guide/concepts"
  • 5. Definitions AngularJS Google’s JavaScript structural framework Extends HTML syntax to seamlessly bind with the app JS A client side solution to building SPA’s Best used with API’s var source = "docs.angularjs.org"
  • 6. Definitions WordPress REST API Proof that WordPress is embracing the concept of front-end applications The WP REST API consists of easy-to-use HTTP endpoints Allow dynamic population of front-end applications with any WordPress data Fastest way to access WordPress data in JSON format
  • 7. Definitions WordPress REST API The WP REST API can be extended to: Modify responses Create internal classes Add endpoints Access custom post types/taxonomies So much more… var source = "developer.wordpress.org/rest-api"
  • 8. Why Single Page Applications? Advantages Incredibly lightweight Rapid deployment Extremely modular Built in mock testing
  • 9. Why Single Page Applications? Challenges Not suited for games, GUI editors, or non-standard DOM manipulation Initial load time Extra effort required for SEO
  • 10. Why Single Page Applications? SPA’s are how sites of the future will be built. It’s already happening: var source = "madewithangular.com"
  • 11. Building a SPA Theme for WordPress Creating a WordPress theme for the SPA Understanding AngularJS SPA components Building an AngularJS SPA Leveraging the WP REST API
  • 12. Creating a WordPress theme for the SPA Folder structure root/ includes assets/ app… img lib/ css js
  • 13. Creating a WordPress theme for the SPA File structure root/ footer.php functions.php header.php index.php style.css
  • 14. Creating a WordPress theme for the SPA File structure root/includes/ enqueue.php
  • 15. Creating a WordPress theme for the SPA File structure root/assets/lib/css/ bootstrap.min.css sizer.css
  • 16. Creating a WordPress theme for the SPA File structure root/assets/lib/js/ angular.min.js angular-sanitize.min.js bootstrap.min.js jquery.min.js ui-route.min.js
  • 17. Creating a WordPress theme for the SPA functions.php <?php /* * Author: Kenneth Schnetz, VendorFuel * URL:vendorfuel.com/spa-theme * Custom functions, support, custom post types and more. */ require_once 'includes/enqueue.php’; add_filter('redirect_canonical', 'no_redirect'); function no_redirect () { return false; } ?>
  • 18. Creating a WordPress theme for the SPA header.php <!doctype html> <html class="m-t-0" ng-app="spaApp" resize ng-cloak> <head> <base href="/"> <title ng-bind="$root.title">SPA Theme</title> <link href="<?php echo get_template_directory_uri(); ?>/assets/img/icons/favicon.ico" rel="shortcut icon"> <link href="<?php echo get_template_directory_uri(); ?>/assets/img/icons/touch.png" rel="apple-touch-icon-precomposed"> <meta name="viewport" content="width=device-width, initial- scale=1.0"> <?php wp_head(); ?> </head> <body> <div ui-view="header"></div
  • 19. Creating a WordPress theme for the SPA index.php <?php get_header(); ?> <div id="content" class="container-fluid" style="height:calc(100vh– 55px);"> <div class="container"> <div ui-view></div> </div> </div> <?php get_footer(); ?>
  • 20. Creating a WordPress theme for the SPA footer.php <div ui-view="footer"></div> </body> </html>
  • 21. Creating a WordPress theme for the SPA style.css /* * Theme Name: SPA Theme * Theme URI: http://vendorfuel.com * Description: SPA Theme for WordPress * Version: 1.0.0 * Author: Ken Schnetz * Author URI: http://vendorfuel.com * Tags: AngularJS, Single Page Application, HTML5, CSS3 */ .active { font-weight: bold; } .card { box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); transition: 0.3s; } .card:hover { box-shadow: 0 10px 20px 0 rgba(0,0,0,0.2); }
  • 22. Creating a WordPress theme for the SPA Enqueueing files Enqueue theme files to allow theme activation Library scripts App scripts Library styles Localized variables NOTE: minify app scripts in production
  • 23. Creating a WordPress theme for the SPA enqueue.php <?php add_action('wp_enqueue_scripts', 'load_assets’); function load_assets() { //lib scripts wp_enqueue_script( 'jquery', get_template_directory_uri() . '/assets/lib/js/jquery.min.js’); wp_enqueue_script( 'bootstrap', get_template_directory_uri() . '/assets/lib/js/bootstrap.min.js’); wp_enqueue_script( 'angular', get_template_directory_uri() . '/assets/lib/js/angular.min.js’); wp_enqueue_script( 'angular-router', get_template_directory_uri() . '/assets/lib/js/ui-route.min.js’); wp_enqueue_script( 'angular-sanitize', get_template_directory_uri() . '/assets/lib/js/angular-sanitize.min.js');
  • 24. Creating a WordPress theme for the SPA enqueue.php //app scripts: ctrl–controller, dir-directive, fac–factory, fil-filter, svc-service wp_enqueue_script( 'app', get_template_directory_uri() . '/assets/app/app.js’); wp_enqueue_script( 'app-config', get_template_directory_uri() . '/assets/app/config.js’); wp_enqueue_script( 'app-run', get_template_directory_uri() . '/assets/app/run.js’); wp_enqueue_script( 'fac-intc', get_template_directory_uri() . '/assets/app/factories/interceptor.js’); wp_enqueue_script( 'svc-post', get_template_directory_uri() . '/assets/app/services/post.js’); wp_enqueue_script( 'svc-page', get_template_directory_uri() . '/assets/app/services/page.js’); wp_enqueue_script( 'dir-resize', get_template_directory_uri() . '/assets/app/directives/resize.js’); wp_enqueue_script( 'ctrl-header', get_template_directory_uri() . '/assets/app/controllers/header.js’); wp_enqueue_script( 'ctrl-home', get_template_directory_uri() . '/assets/app/controllers/home.js’); wp_enqueue_script( 'ctrl-contact', get_template_directory_uri() . '/assets/app/controllers/contact.js’); wp_enqueue_script( 'ctrl-post', get_template_directory_uri() . '/assets/app/controllers/post.js’); wp_enqueue_script( 'ctrl-footer', get_template_directory_uri() . '/assets/app/controllers/footer.js’); //NOTE: these should all be concatenated, minified, and enqueued as one file in production
  • 25. Creating a WordPress theme for the SPA enqueue.php //styles wp_enqueue_style( 'bootstrap', get_template_directory_uri() . '/assets/lib/css/bootstrap.min.css’); wp_enqueue_style( 'sizer', get_template_directory_uri() . '/assets/lib/css/sizer.css’); wp_enqueue_style( 'styles', get_template_directory_uri() . '/style.css');
  • 26. Creating a WordPress theme for the SPA enqueue.php //WordPress variables to be used in SPA wp_localize_script('app', 'localized', array( 'dir' => array( 'url' => get_home_url(), 'root' => get_template_directory_uri(), 'templates' => get_template_directory_uri() . '/assets/app/templates/' ), 'nonce' => wp_create_nonce( 'wp_rest' ) ) ); } ?>
  • 27. Building an AngularJS SPA Understanding the components View: a rendered state of the application State: different parts or “pages” of the site Template: HTML file associated with a specific view Model: the data associated with the application Scope: context where the model is stored and accessed Controller: main logic behind each specific view
  • 28. Building an AngularJS SPA Understanding the components Expression: code snippets in HTML to access scope data Directive: HTML extensions with custom attributes and elements Filter: formats the value of an expression Factory/Service: reusable logic accessible to all controllers Module: container for the different parts of the app
  • 29. Building an AngularJS SPA Folder structure root/assets/app/ controllers directives factories filters services templates
  • 30. Building an AngularJS SPA Base app files root/assets/app/ app.js config.js run.js
  • 31. Building an AngularJS SPA Base app files - app.js Main Module that defines the entire application Minimal amount of code Dependency injection
  • 32. Building an AngularJS SPA Base app files - app.js (function () { 'use strict'; }()); var admin_js_app = admin_js_app || {}; admin_js_app.app = angular.module('spaApp', ['ui.router', 'ngSanitize']);
  • 33. Building an AngularJS SPA Base app files - config.js App configuration file SPA routing and URL settings Defining an HTTP interceptor
  • 34. Building an AngularJS SPA Base app files - config.js admin_js_app.app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', '$provide', '$locationProvider', function($stateProvider, $urlRouterProvider, $httpProvider, $provide, $locationProvider) { $locationProvider.hashPrefix(''); $locationProvider.html5Mode({ enabled: true }); $urlRouterProvider.otherwise('/');
  • 35. Building an AngularJS SPA Base app files - config.js $stateProvider.state('root', { views: { 'header': { templateUrl: localized.dir.templates + '/header.html', controller:'HeaderController' }, 'footer': { templateUrl: localized.dir.templates + '/footer.html', controller:'FooterController' } } })
  • 36. Building an AngularJS SPA Base app files - config.js .state('home', { parent: 'root', url: '/', views: { '@': { templateUrl: localized.dir.templates + 'home.html', controller: 'HomeController' } } })
  • 37. Building an AngularJS SPA Base app files - config.js .state('contact', { parent: 'root', url: '/contact', views: { '@': { templateUrl: localized.dir.templates + 'contact.html', controller: 'ContactController' } } })
  • 38. Building an AngularJS SPA Base app files - config.js .state('post', { parent: 'root', url: '/post', views: { '@': { templateUrl: localized.dir.templates + 'post.html', controller: 'PostController' } } })
  • 39. Building an AngularJS SPA Base app files - config.js $httpProvider.interceptors.push('interceptor’); }]);
  • 40. Building an AngularJS SPA Base app files - run.js App initialization Global scope (rootScope) Perfect for storing localized variables in the model
  • 41. Building an AngularJS SPA Base app files - run.js admin_js_app.app.run(function($rootScope){ $rootScope.rootPath = localized.dir.root; $rootScope.page = 0; $rootScope.title = "SPA Theme"; });
  • 42. Building an AngularJS SPA Views Controller Template Together make up a view
  • 43. Building an AngularJS SPA Views: header - controller admin_js_app.app.controller('HeaderController', function($rootScope, $scope, $http) { jQuery('.navbar-collapse .nav a').on('click', function(){ if(jQuery('.navbar-collapse').hasClass('in')) { jQuery(".navbar-collapse").collapse('hide’); } }); });
  • 44. Building an AngularJS SPA Views: header - template <div id="navigation" class="col-xs-12 p-0"> <nav class="navbar navbar-default m-0"> <div class="container p-0"> <div class="col-xs-12"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data- toggle="collapse" data-target="#myNavbar"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a ui-sref="home"><img class="h-80" ng- src="{{rootPath}}/assets/img/brand.png"></a> </div> <div class="collapse navbar-collapse" id="myNavbar"> <ul class="nav navbar-nav navbar-right p-tb-15"> <li><a ui-sref="home" ng-class="page == 1 ? 'active’ : ''">Home</a></li> <li><a ui-sref="contact" ng-class="page == 2 ? 'active’ : '">Contact</a></li> </ul> </div> </div> </div> </nav> </div>
  • 45. Building an AngularJS SPA Views: header
  • 46. Building an AngularJS SPA Views: home - controller admin_js_app.app.controller('HomeController', function($rootScope, $scope, Post) { $rootScope.page = 1; $scope.loading = true; $rootScope.title = "SPA Theme - Home"; $scope.posts = {}; Post.GetRecent().then(function(p) { if (!p.error) { $scope.posts = p; } $scope.loading = false; }); });
  • 47. Building an AngularJS SPA Views: home - template <div class="col-xs-12 p-0"> <div ng-if="loading" class="col-xs-12 p-0 m-tb-40 text-center"> <img class="h-100" ng-src="{{imagePath}}/loading.gif"> </div> <div ng-if="!loading" ng-repeat="post in posts track by $index" class="col- xs-12 col-md-4 m-t-20 p-0"> <a ng-if="posts" ui-sref="post({ slug:post.slug })"> <div class="col-xs-12 p-20 card"> <div class="col-xs-12 p-0"> <img class="wp-100" ng-src="{{post.thumbnail_url || rootPath + '/assets/img/placeholder.png'}}"> </div> <div class="col-xs-12 p-s-0 p-t-20"> <div class="col-xs-12 p-s-0"> <span class="pull-left"><span ng-bind-html="post.date | date : 'longDate'"></span></span> <span class="pull-right"><span ng-bind- html="post.author"></span></span> </div> <hr class="col-xs-12 p-0"> <div class="col-xs-12 p-0"> <h2 class="text-center m-t-0" ng-bind-html="post.title"></h2> <span ng-bind-html="post.excerpt"></span> </div> </div> </div> </a> </div> </div>
  • 48. Building an AngularJS SPA Views: home
  • 49. Building an AngularJS SPA Views: footer - controller admin_js_app.app.controller('FooterController', function($rootScope, $scope) {});
  • 50. Building an AngularJS SPA Views: footer - template <div class="col-xs-12 p-0"> <footer id="footer" class="navbar navbar-default m-0"> <div class="container p-20 text-center"> &copy; 2018 Copyright VendorFuel </div> </footer> </div>
  • 51. Building an AngularJS SPA Views: footer
  • 52. Building an AngularJS SPA Views: header, home, footer combined
  • 53. Building an AngularJS SPA Directives Extended HTML attributes with the ng- prefix Many built in directives ng-app ng-model ng-bind etc… You can define your own directives Resize: get current screen width in relation to bootstrap columns (xs, sm, md, lg)
  • 54. Building an AngularJS SPA Directives - resize admin_js_app.app.directive('resize', function($window) { return function($scope) { GetSizing(); angular.element($window).bind('resize', function() { $scope.$apply(function() { GetSizing(); }); }); function GetSizing() { $scope.width = $window.innerWidth; CheckSizing($scope.width); }; function CheckSizing(w) { if (w < 768) { SetBools(true); } else if ((w >= 768) && (w < 992)) { SetBools(false, true); } else if ((w >= 992) && (w < 1200)) { SetBools(false, false, true);} else { SetBools(false, false, false, true); } }; function SetBools(xs = false, sm = false, md = false, lg = false) { $scope.isXS = xs; $scope.isSM = sm; $scope.isMD = md; $scope.isLG = lg; }; }; });
  • 55. Building an AngularJS SPA Factories Global functionality provided to the controllers Provides modularized global functionality You can define your own factories Interceptor: modify HTTP requests and responses
  • 56. Building an AngularJS SPA Factories - interceptor admin_js_app.app.factory('interceptor', ['$q', function($q) { return { request: function(config) { config.headers['X-WP-Nonce'] = localized.nonce; return config || $q.when(config); }, requestError: function(rejection) { return $q.reject(rejection); }, response: function(response) { return response || $q.when(response); }, responseError: function(rejection) { return $q.reject(rejection); } }; }]);
  • 57. Building an AngularJS SPA Services Similar to factories Provides modularized global functionality Many built in services: $http $location $timeout etc… You can define your own services Leveraging the WP REST API is a perfect use case
  • 58. Leveraging the WP REST API Provides API endpoints for WordPress data types Sends and receives JSON objects Extremely simple to use NOTE: you will need a localized nonce to utilize the WP REST API fully from a SPA
  • 59. Leveraging the WP REST API Use case examples yoursite.com/wp-json/v2/ pages pages?slug=spa-contact posts posts?id=1 Will not have linked data posts?_embed&id=1 Will have linked data
  • 60. Leveraging the WP REST API Page Page with a contact form via shortcode Page service Page controller Page template
  • 61. Leveraging the WP REST API Page - content WordPress page content in this example: <h3 style="text-align: center;"> Please fill out your contact info and we will get back to you shortly! </h3> <div style="text-align: center;"> [contact-form-7 id="5" title="Contact form 1"] </div>
  • 62. Leveraging the WP REST API Page - service admin_js_app.app.service('Page', function($rootScope, $http, $sce) { this.GetSlug = function (slug) { var req = { method: 'GET', url: localized.dir.url + '/wp- json/wp/v2/pages?slug=' + slug }; var promise = $http(req).then(function(resp){ var page = {}; if (resp.data[0]) { page.id = resp.data[0].id; page.title = $sce.trustAsHtml(resp.data[0].title.rendered); page.content = $sce.trustAsHtml(resp.data[0].content.rendered); } else { page.error = "Page not found"; } return page; }, function(resp){ return resp; }); return promise; } });
  • 63. Leveraging the WP REST API Page - controller admin_js_app.app.controller('ContactController', function($rootScope, $scope, Page) { $rootScope.page = 2; $scope.loading = true; $rootScope.title = "SPA Theme - Contact"; Page.GetSlug("contact").then(function(p) { if (p.error) { $scope.pageTitle = p.error; } else { $scope.pageTitle = p.title; $scope.pageContent = p.content; } $scope.loading = false; }); });
  • 64. Leveraging the WP REST API Page - template <div ng-if="loading" class="col-xs-12 p-0 m-tb-40 text-center"> <img class="h-100" ng-src="{{imagePath}}/loading.gif"> </div> <div ng-if="!loading" class="col-xs-12 p-0 m-tb-40"> <h1 ng-bind="pageTitle"></h1> <hr class="col-xs-12"> <div class="col-xs-12" ng-bind-html="pageContent"></div> </div>
  • 65. Leveraging the WP REST API Page - view
  • 66. Leveraging the WP REST API Post Post with content For this example: hello-world Post service Post controller Post template
  • 67. Leveraging the WP REST API Post – service admin_js_app.app.service('Post', function($rootScope, $http, $sce) { this.GetSlug = function (slug) { var req = { method: 'GET', url: localized.dir.url + '/wp- json/wp/v2/posts?_embed&slug=' + slug }; var promise = $http(req).then(function(resp){ var post = resp.data[0]; var tempPost = {}; if (post) { tempPost = { id: post.id, slug: post.slug, date: FormatDate(post.date), author: post._embedded.author[0].name, title: $sce.trustAsHtml(post.title.rendered), excerpt: $sce.trustAsHtml(post.excerpt.rendered), content: $sce.trustAsHtml(post.content.rendered) }; } else { tempPost.error = "Post not found"; } return tempPost; }, function(resp){ return resp; }); return promise; };
  • 68. Leveraging the WP REST API Post – service this.GetRecent = function (count = 6) { var req = { method: 'GET', url: localized.dir.url + '/wp- json/wp/v2/posts?_embed&per_page=' + count }; var promise = $http(req).then(function(resp){ var posts = []; var tempPost = {}; if (resp.data) { angular.forEach(resp.data, function(value) { tempPost = { id: value.id, slug: value.slug, date: FormatDate(value.date), author: value._embedded.author[0].name, title: $sce.trustAsHtml(value.title.rendered), excerpt: $sce.trustAsHtml(value.excerpt.rendered), content: $sce.trustAsHtml(value.content.rendered)}; posts.push(tempPost); }); return posts.reverse(); } else { post.error = "Post not found"; } return post; }, function(resp){ return resp; }); return promise; };
  • 69. Leveraging the WP REST API Post – service function FormatDate(d) { var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; var dt = new Date(d); return months[dt.getMonth()] + " " + dt.getDate() + ", " + dt.getFullYear(); }; });
  • 70. Leveraging the WP REST API Post – controller admin_js_app.app.controller('PostController', function($rootScope, $scope, $stateParams, Post) { $rootScope.page = 0; $scope.loading = true; $scope.slug = $stateParams.slug; $rootScope.title = "SPA Theme - " + $scope.slug; $scope.post = {}; Post.GetSlug($scope.slug).then(function(p) { $scope.post.error = false; if (p.error) { $scope.post.title = p.error; $scope.post.error = true; } else { $scope.post = p; } $scope.loading = false; }); });
  • 71. Leveraging the WP REST API Post – template <div ng-if="loading" class="col-xs-12 p-0 m-tb-40 text-center"> <img class="h-100" ng-src="{{imagePath}}/loading.gif"> </div> <div ng-if="!loading" class="col-xs-12 p-0 m-tb-40"> <h1 ng-bind="post.title"></h1> <hr class="col-xs-12 p-0"> <span ng-bind="post.date" class="pull-left"></span> <span ng-bind="post.author" class="pull-right"></span> <hr ng-if=“!post.error" class="col-xs-12 p-0"> <div class="col-xs-12 p-0" ng-bind-html="post.content"></div> </div>
  • 72. Leveraging the WP REST API Post – view
  • 73. Conclusion SPA examples and FREE SPA theme source code – see me in the lobby! Thank you for stopping by.