Utiliser un backoffice sous Wordpress avec AngularJS
L’objectif de ce tutoriel et de découvrir les bases pour développer un site internet ou une application web sous AngularJS avec un Wordpress comme solution de backoffice.
Dans de nombreux cas, on souhaite avoir une partie administration qui permette simplement à un ensemble de personnes de rajouter du contenu textuel ou média (images, vidéos)
Ces mêmes personnes ayant un rôle différent dans l’administration du site/application.
Par défaut, Wordpress est limité en terme de champs complémentaires dans les articles, c’est pourquoi nous allons installer le plugin Advanced Custom Fields.
Enfin, pour dialoguer avec la base de données, nous allons utiliser le format json au travers d’une API exposée par le plugin json-api
demo : http://dcz-lab.fr/wordpress_angularjs/
Préparation du backoffice
Bien que l’installation de wordpress puisse se faire à la racine du serveur, nous allons ici considérer que wordpress ne va servir qu’à l’administration, nous allons donc le placer dans un répertoire “wordpress” A la racine du serveur on trouvera le fichier index.html et notre page avec AngularJS
Bien entendu, vous pouvez faire autrement, cette organisation n’est là que pour le tutoriel
Voici comment nous allons organiser nos répertoires :
/wordpress /js /libs angular.min.js angular-route.min.js app.js controllers.js /partials post.html index.html
Donc, après avoir installé Wordpress dans un répertoire du même nom, installez et activez les plugins suivants
Advanced Custom Fields (ACF) https://wordpress.org/plugins/advanced-custom-fields/
json-api et ACF
Le plugin json-api fonctionne parfaitement pour les champs de type custom fields, mais ne retourne pas correctement les champs gérés par ACF car au lieu de récupérer un ensemble d’objets, on récupère une chaîne de caractères.
Pour régler ça, il suffit d’ajouter les lignes suivantes en fin de fichier
/wp-content/plugins/json-api/json-api.php
// support des champs du plugin Advanced Custom Fields add_filter('json_api_encode', 'json_api_encode_acf'); function json_api_encode_acf ($response) { if (isset($response['posts'])) { foreach ($response['posts'] as $post) { json_api_add_acf($post); // Add specs to each post } } else if (isset($response['post'])) { json_api_add_acf($response['post']); // Add a specs property } return $response; } function json_api_add_acf (&$post) { $post->acf = get_fields($post->id); }
les smart quotes de Wordpress
Un autre comportement propre à Wordpress et l’utilisation des “smart quotes” pour remplacer les quotes et double quotes (apostrophes et guillemets) Le problème c’est que lorsqu’ils seront récupérés par json-api, on aura la traduction html et non le caractère.
Pour régler ça, on ajoute à la fin du fichier les lignes suivantes /wp-content/themes/votre_theme/functions.php
remove_filter('the_content', 'wptexturize'); remove_filter('comment_text', 'wptexturize'); remove_filter ('single_post_title', 'wptexturize'); remove_filter ('the_title', 'wptexturize'); remove_filter ('wp_title', 'wptexturize');
Le backoffice est prêt, on va l’étoffer un peu avant de passer à notre application/site Ajout d’un peu de contenu dans notre backoffice
Nous allons enrichir un peu le backoffice pour avoir quelque chose à afficher.
Pour ceux qui ne connaissent pas, ça sera aussi l’occasion d’avoir un premier aperçu de comment fonctionne le plugin Advanced Custom Fields
ACF Dans le menu de l’administration de Wordpress, vous deviez avoir une entrée ACF Sélectionnez la et ajoutez un nouveau “Groupe de champs”
Donnez lui un nom, par exemple “tutoriels”
Ajoutez ensuite dans ce groupe 2 champs, par exemple un champ “une image” de type “image” un champ “utile” de type “bouton radio” obligatoire avec les valeurs “Oui” et ”Non”
N’oubliez pas de publier !
Vous devriez obtenir quelque chose dans ce goût là :
Création d’un nouvel article
Par défaut, les champs ACF seront disponibles dans tous vos articles.
Allez dans le menu Articles et ajoutez un article
En dessous du texte de l’article, vous devriez retrouver les 2 champs ACF créés précédemment.
Mettez un titre, un peu de contenu dans l’article, renseignez les 2 champs ACF
Publiez !
Inutile d’ajouter plus de contenu pour l’instant, passons au développement de l’application/site.
Développement de l’application/site
Nous allons simplement afficher sur une page la liste des articles et afficher leur détail.
Voici donc ce qu’on va obtenir : la liste des articles et si on sélectionne un article, son titre et contenu qui apparaissent en dessous
Pour la suite, je vous invite fortement à afficher les outils pour développeurs du votre navigateur, ne serait-ce que pour vérifier le bon chargement des données
Pour commencer, le HTML
index.html
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Wordpress - angularJS</title> <script src="js/libs/angular.min.js"></script> <script src="js/libs/angular-route.min.js"></script> </head> <body ng-app="wpApp"> <div ng-controller="listeCtrl"> <h1>Les articles Wordpress affichés par angularJS</h1> <ul> <li ng-repeat="post in posts"> <a href="#/post/{{post.id}}">{{post.title}}</a> </li> </ul> </div> <div> <div ng-view></div> </div> <script src="js/app.js"></script> <script src="js/controllers.js"></script> </body> </html>
Dans le fichier index.html, on retrouve : la déclaration de l’application (wpApp) le controller qui va récupérer la liste des articles (ListeCtrl) l’affichage de la liste des articles avec la directive ng-repeat la directive ng-view pour afficher le détail d’un article
partials/post.html
<div> <h2>{{post.title}}</h2> <h4>détail du post {{post.id}}</h4> <p> {{post.content}} </p> <p ng-bind-html='content'></p> </div>
Ce morceau de html va servir à afficher le détail d’un vue en étant chargé dans la directive ng-view
Vous remarquez que le contenu est affiché de 2 manières :
{{post.content}} <p ng-bind-html=’content’></p>
Ceci pour présenter une particularité d’Angular qui protège de l’injection de code le chargement de données.
Si vous affichez la page avec ce code complet, vous verez le code html et en dessous l’article mis en forme.
Un peu de patience, j’explique plus loin comment ça fonctionne et à quoi sert la directive ng-bind-html
Les fichiers JS
js/app.js
var wpApp = angular.module('wpApp', ['ngRoute', 'wpAppControllers']); /** * * définition des routes * */ wpApp.config(['$routeProvider', function ($routeProvider) { $routeProvider. when('/post/:postId', { templateUrl: 'partials/post.html', controller: 'postCtrl' }); } ]);
Ici on crée l’application en chargeant les modules ngRoute pour la navigation et le module qui regroupe nos controllers
js/controllers.js
var wpAppControllers = angular.module('wpAppControllers', []); /** * * affichage de la liste des posts * */ var listeCtrl = wpAppControllers.controller('listeCtrl', ['$scope', '$http', function ($scope, $http) { $http.get('../wordpress/?json=get_recent_posts').success( function (data) { $scope.posts = data.posts; }); }]); /** * * affichage d'un post * * le chargement de sce est nécessaire pour le rendu html dans la page * */ var postCtrl = wpAppControllers.controller('postCtrl', ['$scope', '$http', '$routeParams', '$sce', function ($scope, $http, $routeParams, $sce) { $http.get('../wordpress/?json=get_post&post_id=' + $routeParams.postId).success( function (data) { $scope.post = data.post; $scope.content = $sce.trustAsHtml(data.post.content); }); }]);
Il y a logiquement deux controllers
- le premier va récupérer la liste des posts,
- le deuxième va récupérer le détail d’un seul article dont l’id lui aura été transmis dans l’URL ($routeParams)
Dans la documentation du plugin json_api, il est expliqué que deux méthodes permettent de récupérer les infos : une méthode dite implicite, l’autre appelée explicite.
N’hésitez pas à tester vous même.
Méthode implicite
Chargement de la liste des posts : 459ms
Chargement d’un article : 488ms (238 + 250)
Méthode explicite
Chargement de la liste des posts : 259ms
Chargement d’un article : 291ms
méthode “trustAsHtml()”
Comme expliqué plus haut, pour éviter de charger du code malicieux, AngularJS protège le chargement de données.
Pour indiquer à Angular que tout va bien, on charge dans le 2eme controller le module $sce On utilise ensuite la méthode trustAsHtml( ) pour indiquer que le HTML récupéré est propre.
Bonus : Angular Batarang extension
Si vous envisagez de développer sous Angular, il peut-être intéressant de disposer d’un outil pour afficher le contenu du $scope de chaque controller.
Une extension aux navigateurs a été développée pour Chrome et Firefox
https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk
Conclusion
Voilà, vous êtes maintenant en mesure d'utiliser Wordpress comme backoffice de votre site ou application web basé sur AngularJS !
