Création d'une Single Page Application avec WordPress et Angular.js
() translation by (you can also view the original English article)



Travailler sur un projet avec le framework Angular.js est rapide et gratifiant; sa combinaison avec WordPress peut nous permettre de réaliser rapidement une chouette SPA (Single Page Application). Les plugins et contrôles que nous offre WordPress vont nous permettre de faciliter le développement.
Réglage du thème
Nous allons commencer par créer un nouveau thème basé sur le thème générique _tk
. Il s'agit d'une implementation du thème _s
underscores créé par Automattic qui intègre le framework Bootstrap.
Téléchargez le thème depuis Github et placez les fichiers dans votre répertoire themes
1 |
$ cd themes |
2 |
$ wget https://github.com/Themekraft/_tk/archive/master.zip
|
3 |
wp-content/themes/$ unzip master.zip
|
4 |
Archive: master.zip |
5 |
69acda231e2a2f8914374df81b89a7aa37d594fa |
6 |
creating: _tk-master/ |
7 |
inflating: _tk-master/404.php |
8 |
inflating: _tk-master/archive.php |
9 |
inflating: _tk-master/comments.php |
10 |
inflating: _tk-master/content-page.php |
11 |
inflating: _tk-master/content-single.php |
12 |
... |
13 |
## Rename The Directory
|
14 |
$ mv _tk-master/ angular-bootstrap |
15 |
$ rm -f master.zip |
Maintenant que notre thème _tk
est en place, nous aurons besoin des packages npm
angular
et angular-routes
à l'intérieur de notre répertoire de thème (nous utiliserons le nom angular-bootstrap
)
1 |
$ cd wp-angular |
2 |
$ npm init
|
3 |
#follow the prompts to create your package.json file
|
4 |
... |
5 |
"author": "", |
6 |
"license": "ISC" |
7 |
}
|
8 |
|
9 |
|
10 |
Is this ok? (yes) yes |
11 |
## Install The Packages
|
12 |
$ $ npm install angular angular-route --save |
- On doit maintenant initialiser
npm
dans le répertoire thèmes avecnpm init
pour créer le fichierpackage.json
, fichier quenpm
utilise pour gérer les projets. - En utilisant le flag
--save
dans notre commandenpm install angular angular-route --save
nous informonsnpm
d'ajouter le module en tant que dépendance de notre projet. - Si pour la suite nous devions partager ce projet avec d'autres développeurs, il leur suffirai de lancer la commande
npm install
dans le même répertoire que le fichierpackage.json
pour récupérer les packages.
Les packages seront installées dans le répertoire node_modules
à l'intérieur de votre thème. Si vous regardez dans ce dossier vous verrez plusieurs fichier JS. Pour le développement de notre application nous utiliserons angular.min.js
Initialisation d'Angular
Afin de pouvoir inclure le script angular.min.js
dans WordPress, nous devons modifier le ficher functions.php
.
Dans functions.php, recherchez la function _tk_scripts()
et ajoutez le code suivant à la suite:
1 |
//Load angular
|
2 |
wp_enqueue_script('angularjs', get_template_directory_uri() .'/node_modules/angular/angular.min.js'); |
3 |
wp_enqueue_script('angularjs-route', get_template_directory_uri() .'/node_modules/angular-route/angular-route.min.js'); |
4 |
wp_enqueue_script('scripts', get_stylesheet_directory_uri() . '/js/scripts.js', array( 'angularjs', 'angularjs-route' )); |
Vous devrez également créer js/scripts.js
- pour le moment, créez juste un fichier vierge.
Rafraichissez maintenant votre navigateur et dans les outils de développement vous devriez apercevoir angular.min.js
qui est maintenant inclus.
Utilisation de partials
Angular.js permet de ne mettre à jour que certains fragments de code HTML. Afin d'exploiter ces possibilités et celles du module angular-route
nous devons créer un répertoire à l'intérieur du thème que l'on nommera partials
.
1 |
$ mkdir partials |
Dans le répertoire partials
, créez un ficher nommé main.html
qui nous servira de test et ajoutez du code HTML dedans.
Localisation du chemin des partials dans WordPress
Pour qu'Angular soit capable de charger ces fragments nous devons lui fournir une URL complète. J'ai eu des difficultés à utiliser la méthode get_stylesheet_directory_uri()
mais vous pouvez vous y essayer. Si cela ne fonctionne pas, utiliser l'URL complète.
Ajoutez le code suivant à la fonction _tk_scripts
ci dessous, à l'endroit où vous avez ajouté angularjs
et angular-route
précédemment:
1 |
// With get_stylesheet_directory_uri()
|
2 |
wp_localize_script('scripts', 'localized', |
3 |
array( |
4 |
'partials' => get_stylesheet_directory_uri() . '/wp-content/themes/angular-bootstrap/partials/' |
5 |
)
|
6 |
);
|
Si cela échoue (ce qui m'est arrivé au moment où je rédige ces lignes), écrivez "en dur" l'URL comme suit:
1 |
// With hardcoded value
|
2 |
wp_localize_script('scripts', 'localized', |
3 |
array( |
4 |
'partials' => 'https://www.mydomaind.com/wp-content/themes/angular-bootstrap/partials/' |
5 |
)
|
6 |
);
|
Activer WP-API
Pour qu'Angular puisse travailler conjointement avec WordPress, nous devons activer le plugin WP-API REST. Cette manipulation est simple, il s'agit simplement d'installer un plugin.
Téléchargez et installez le plugin depuis git et lancez la commande suivante dans votre répertoire plugins
:
1 |
git clone git@github.com:WP-API/WP-API.git json-rest-api |
Activez ensuite le plugin dans le panneau wp-admin
. Vous pourrez voir le résultat au format JSON à your-wordpress.com/wp-json
une fois celui-ci activé.
Route de l'applications
Les routes représentent les pages spécifiques de votre blog. Nous pouvons en définir une pour notre partial main.html
tout de suite et la configurer pour apparaitre sur la page d'index de notre WordPress.
Premièrement, assurez vous que l'application Angular.js soit bien définie via l'attribut ng-app
et insérez le code ci-dessous dans header.php
:
1 |
<!DOCTYPE html>
|
2 |
|
3 |
<html <?php language_attributes(); ?> ng-app="wp"> |
4 |
<head>
|
5 |
<base href="/"> |
Nous appelons ici l'application wp
grâce à l'attribut ng-app
. Nous insérons également la balise base
pour qu'Angular soit en mesure de trouver le JSON que nous avons activé dans WP-API
.
Ajouter ce qui suit à js/scripts.js
:
1 |
angular.module('wp', ['ngRoute']) |
2 |
.config(function($routeProvider, $locationProvider) { |
3 |
$routeProvider
|
4 |
.when('/', { |
5 |
templateUrl: localized.partials + 'main.html', |
6 |
controller: 'Main' |
7 |
})
|
8 |
})
|
9 |
.controller('Main', function($scope, $http, $routeParams) { |
10 |
$http.get('wp-json/posts/').success(function(res){ |
11 |
$scope.posts = res; |
12 |
});
|
13 |
});
|
Maintenant dans partials/main.html
ajoutez le code suivant:
1 |
<ul>
|
2 |
<li ng-repeat="post in posts"> |
3 |
<a href="{{post.slug}}"> |
4 |
{{post.title}} |
5 |
</a>
|
6 |
</li>
|
7 |
</ul>
|
Enfin dans index.php
juste après get_header()
ajoutez l'attribut ng-view
à une balise div
.
1 |
<div ng-view></div> |
Rafraichissez la page d'index de votre site et une liste à puce des articles est maintenant affichée sur la page d'accueil.
Ce résultat est obtenu via la directive ng-controller
qui invoque le controller Main
depuis scripts.js
; l'attribut ng-view
spécifie dans quelle partie de l'application Angular doit afficher les informations.
Affichage d'un article par slug
Ajoutons maintenant une route pour afficher un article par slug.
Ouvrons le fichier js/scripts.js
et ajoutons le code suivant:
1 |
angular.module('wp', ['ngRoute']) |
2 |
.config(function($routeProvider, $locationProvider) { |
3 |
|
4 |
$routeProvider
|
5 |
.when('/', { |
6 |
templateUrl: localized.partials + 'main.html', |
7 |
controller: 'Main' |
8 |
})
|
9 |
.when('/:slug', { |
10 |
templateUrl: localized.partials + 'content.html', |
11 |
controller: 'Content' |
12 |
})
|
13 |
.otherwise({ |
14 |
redirectTo: '/' |
15 |
});
|
16 |
})
|
17 |
.controller('Main', function($scope, $http, $routeParams) { |
18 |
$http.get('wp-json/posts/').success(function(res){ |
19 |
$scope.posts = res; |
20 |
});
|
21 |
})
|
22 |
.controller('Content', |
23 |
['$scope', '$http', '$routeParams', function($scope, $http, $routeParams) { |
24 |
$http.get('wp-json/posts/?filter[name]=' + $routeParams.slug).success(function(res){ |
25 |
$scope.post = res[0]; |
26 |
});
|
27 |
}
|
28 |
]
|
29 |
);
|
En ajoutant le controller Content
nous spécifions l'URI $http.get
pour les articles au format JSON et spécifions le slug
en tant que paramètre de filtre.
Pour ce faire nous utilisons le code suivant: $http.get('wp-json/posts/?filter[name]=' + $routeParams.slug)
.
Note: pour que la route /:slug
fonctionne, nous devons spécifier /%postname%/
en tant que structure de permalien dans wp-admin
.
Assurez vous d'ajouter le code suivant dans content.html
1 |
<h1>{{post.title}}</h1> |
2 |
{{post.content}} |
Si maintenant vous rafraichissez la page, vous êtes en mesure de naviguer sur votre blog grâce aux liens de la liste à puce réalisés précédemment.
Utilisation des services d'Angular dans WordPress
Nous avons jusqu'ici abordé comment créer des routes et avons commencé à travailler avec l'API wp-json
. Avant de développer la logique, nous devons déjà la placer dans un endroit cohérent de notre application; cet endroit est un service
Angular (dans cette exemple nous utiliserons une factory
)
Créez un nouveau ficher js/services.js
et ajoutez le code suivant qui nous permettra de récupérer les catégories et les articles:
1 |
|
2 |
function ThemeService($http) { |
3 |
|
4 |
var ThemeService = { |
5 |
categories: [], |
6 |
posts: [], |
7 |
pageTitle: 'Latest Posts:', |
8 |
currentPage: 1, |
9 |
totalPages: 1, |
10 |
currentUser: {} |
11 |
};
|
12 |
|
13 |
//Set the page title in the <title> tag
|
14 |
function _setTitle(documentTitle, pageTitle) { |
15 |
document.querySelector('title').innerHTML = documentTitle + ' | AngularJS Demo Theme'; |
16 |
ThemeService.pageTitle = pageTitle; |
17 |
}
|
18 |
|
19 |
//Setup pagination
|
20 |
function _setArchivePage(posts, page, headers) { |
21 |
ThemeService.posts = posts; |
22 |
ThemeService.currentPage = page; |
23 |
ThemeService.totalPages = headers('X-WP-TotalPages'); |
24 |
}
|
25 |
|
26 |
ThemeService.getAllCategories = function() { |
27 |
//If they are already set, don't need to get them again
|
28 |
if (ThemeService.categories.length) { |
29 |
return; |
30 |
}
|
31 |
|
32 |
//Get the category terms from wp-json
|
33 |
return $http.get('wp-json/taxonomies/category/terms').success(function(res){ |
34 |
ThemeService.categories = res; |
35 |
});
|
36 |
};
|
37 |
|
38 |
ThemeService.getPosts = function(page) { |
39 |
return $http.get('wp-json/posts/?page=' + page + '&filter[posts_per_page]=1').success(function(res, status, headers){ |
40 |
ThemeService.posts = res; |
41 |
page = parseInt(page); |
42 |
|
43 |
// Check page variable for sanity
|
44 |
if ( isNaN(page) || page > headers('X-WP-TotalPages') ) { |
45 |
_setTitle('Page Not Found', 'Page Not Found'); |
46 |
} else { |
47 |
//Deal with pagination
|
48 |
if (page>1) { |
49 |
_setTitle('Posts on Page ' + page, 'Posts on Page ' + page + ':'); |
50 |
} else { |
51 |
_setTitle('Home', 'Latest Posts:'); |
52 |
}
|
53 |
|
54 |
_setArchivePage(res,page,headers); |
55 |
}
|
56 |
});
|
57 |
};
|
58 |
|
59 |
return ThemeService; |
60 |
}
|
61 |
|
62 |
//Finally register the service
|
63 |
app.factory('ThemeService', ['$http', ThemeService]); |
64 |
Il s'agit d'une factory basique dans laquelle nous avons deux méthodes: _setTitle
et _setArchivePage
. Ces méthodes sont appelées depuis getPosts
et getCategories
afin de mettre à jour le titre de la page courante et également pour définir un nombre entier nous permettant de connaitre le numéro de la page à chercher.
Nous aurons besoin du module ngSanitize
pour parser les inputs utilisateurs de notre service. A l'intérieur de votre répertoire de thème, installez le avec npm
:
1 |
$ npm install angular-sanitize --save |
themeService
est un objet Javascript basique qui effectue une recherche de catégorie via $http.get
comme le fait la méthode getPosts
. Initialisons maintenant ce service dans notre contrôlleur. Ouvrez scripts.js
et modifiez le contrôlleur pour lui passer ThemeService
.
1 |
//Main controller
|
2 |
app.controller('Main', ['$scope', '$http', 'ThemeService', function($scope, $http, ThemeService) { |
3 |
//Get Categories from ThemeService
|
4 |
ThemeService.getAllCategories(); |
5 |
|
6 |
//Get the first page of posts from ThemeService
|
7 |
ThemeService.getPosts(1); |
8 |
|
9 |
$scope.data = ThemeService; |
10 |
}]);
|
N'oubliez pas d'activer le module angular-sanitize
dans votre scripts.js
également à la première ligne avec le code suivant:
1 |
var app = angular.module('wp', ['ngRoute', 'ngSanitize']); |
Enfin, assurez vous que le fichier js/services.js
et le module angular-sanitize
soient bien mis à disposition de WordPress. Pour ce faire, modifions le fichier functions.php
and ajoutons le code suivant juste avant l'appel à wp_localize_script
:
1 |
wp_enqueue_script('angularjs-sanitize', get_stylesheet_directory_uri() . '/node_modules/angular-sanitize/angular-sanitize.min.js'); |
2 |
wp_enqueue_script('theme-service', get_stylesheet_directory_uri() . '/js/services.js'); |
Nous devons maintenant mettre à jour le fragment dans le fichier main.html afin que celui-ci puisse afficher les catégories misent à disposition pour le ThemeService.
1 |
<h1>Categories</h1> |
2 |
<ul>
|
3 |
<li ng-repeat="category in data.categories"> |
4 |
<span ng-if="current_category_id && category.ID == current_category_id" ng-bind-html="category.name"></span> |
5 |
<a ng-if="!current_category_id || category.ID != current_category_id" href="category/{{category.slug}}" ng-bind-html="category.name"></a> |
6 |
</li>
|
7 |
</ul>
|
8 |
|
9 |
<p>{{data.pageTitle}}</p> |
10 |
<ul>
|
11 |
<li ng-repeat="post in data.posts"> |
12 |
<a href="/{{post.slug}}" ng-bind-html="post.title"></a> |
13 |
<a href="/{{post.slug}}" ng-if="post.featured_image_thumbnail_url"><img ng-src="{{post.featured_image_thumbnail_url}}" alt="{{post.featured_image.title.rendered}}" /></a> |
14 |
<div ng-bind-html="post.excerpt.rendered"></div> |
15 |
</li>
|
16 |
</ul>
|
Vous devriez maintenant être en mesure de voir s'afficher les articles et catégories dans votre page d'accueil grâce à ng-view
et une factory
d'Angular. Grâce à cette démarche les données seront disponibles par tous les composants de notre application. Et nous pouvons maintenant partager l'objet des catégories avec tous nos contrôlleurs dans nos routes.
Pour aller plus loin
Maintenant que nous avons un service prêt dans notre thème, nous pouvons continuer à développer la couche modèle et incorporer le style de Bootstrap dans le HTML généré par notre application.
Maintenant qu'Angular est configuré dans votre thème les possibilités sont réellement infinies. En parcourant le repo fourni, vous aurez un rapide point de départ pour développer une application single-page avec Angular et Bootstrap.