Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Utiliser un backoffice sous Wordpress avec AngularJS

Par dcz.switcher (dcz.switcher), le 08 juin 2014

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érequis disposer d’un serveur web pour y installer Wordpress avoir des notions sur AngularJS est un plus, mais n’est pas indispensable

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 http://wordpress.org/plugins/json-api/

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.

je ne vais pas m’étendre ici sur AngularJS, il est d’ailleurs tout à fait possible de réaliser la même chose en Vanilla ou avec jQuery, BackboneJS ou jeNeSaisQuelleAutreLibrairieJS

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

  1. le premier va récupérer la liste des posts,
  2. 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.

Il y a une différence notable de temps de chargement entre les deux premières, comme on peut le voir sur les images ci-dessous.

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 !