Home » wordpress » Filtrer ses custom post type et ajouter un bouton load more
Filtrer ses custom post type et ajouter un bouton load more
Comment rajouter des filtres et un bouton load more à ses custom post type ?
Dans un précédent article, j’ai montré un exemple d’implémentation, à partir des articles classiques, d’une fonction de filtrage et de rechargement en ajax des articles.
Ici on va voir comment pousser encore plus loin ce système en l’étendant aux custom post type. Voici un rendu possible : on a nos différents filtres tout en haut, et un bouton de rechargement d’articles en ajax tout en bas.
Création du custom post type
Je pars du même exemple que précédemment : je crée un custom post type appelé « formation ». Je lui attribue deux taxonomies : « categorie-formations » et « niveau-formation« . Ces taxonomies ont comme argument : ‘hierarchical’ => true », : cela permet entre autre d’avoir des cases à cocher dans le backoffice, comme pour des catégories classiques.
<?php function cc_formation_cpt() { /* Formation */ $labels = array( 'name' => _x('Formations', 'Post Type General Name', 'text_domain'), 'singular_name' => _x('Formation', 'Post Type Singular Name', 'text_domain'), 'menu_name' => _x('Formations', 'text_domain'), 'name_admin_bar' => _x('Formations', 'text_domain'), 'all_items' => _x('Toutes les formations', 'text_domain'), 'add_new_item' => _x('Ajouter une nouvelle formation', 'text_domain'), 'add_new' => _x('Ajouter', 'text_domain'), 'new_item' => _x('Nouvelle formation', 'text_domain' ), 'edit_item' => _x('Editer la formation', 'text_domain'), 'update_item' => _x('Mettre à jour la formation', 'text_domain'), 'view_item' => _x('Voir la formation', 'text_domain'), 'search_items' => _x('Rechercher une formation', 'text_domain'), 'not_found' => _x('Aucune formation trouvée', 'text_domain'), 'not_found_in_trash' => _x('Aucune formation trouvée dans la corbeille', 'text_domain'), );
$labels_cat_formation = array( 'name' => _x( 'Catégories de la formation', 'taxonomy general name'), 'singular_name' => _x( 'Catégories de la formation', 'taxonomy singular name'), 'search_items' => __( 'Rechercher une catégorie'), 'popular_items' => __( 'Catégories populaires'), 'all_items' => __( 'Toutes les catégories'), 'edit_item' => __( 'Editer une catégorie'), 'update_item' => __( 'Mettre à jour une catégorie'), 'add_new_item' => __( 'Ajouter une nouvelle catégorie'), 'new_item_name' => __( 'Nom de la nouvelle catégorie'), 'add_or_remove_items' => __( 'Ajouter ou supprimer une catégorie'), 'choose_from_most_used' => __( 'Choisir parmi les catégories les plus utilisées'), 'not_found' => __( 'Pas de catégories trouvée'), 'menu_name' => __( 'Catégorie de formation'), );
$labels_level_formation = array( 'name' => _x( 'Niveaux de la formation', 'taxonomy general name'), 'singular_name' => _x( 'Niveau de la formation', 'taxonomy singular name'), 'search_items' => __( 'Rechercher un niveau'), 'popular_items' => __( 'Niveaux populaires'), 'all_items' => __( 'Tous les Niveaux'), 'edit_item' => __( 'Editer un niveau'), 'update_item' => __( 'Mettre à jour un niveau'), 'add_new_item' => __( 'Ajouter un nouveau niveau'), 'new_item_name' => __( 'Nom de le nouveau niveau'), 'add_or_remove_items' => __( 'Ajouter ou supprimer un niveau'), 'choose_from_most_used' => __( 'Choisir parmi les nivexau les plus utilisées'), 'not_found' => __( 'Pas de niveau trouvé'), 'menu_name' => __( 'Niveau de formation'), );
Je crée ensuite ma page d’archive page-formation.php pour mon custom post type. Normalement, en passant l’argument has_archive à true, wordpress va automatiquement générer une page d’archive pour notre custom post type. Il suffira alors d’aller la chercher dans Apparence / Menu et de la placer dans le menu. Le problème c’est que cette page est « fictive », dans le sens où elle n’existe pas en dur dans le dossier wordpress. On ne peut donc pas l’administrer.
Dans mon exemple, j’ai forcément besoin de pouvoir la personnaliser puisque je veux y inclure mon système de filtre et le bouton ajax load more. Je veux aussi donner la possibilité à l’utilisateur final de pouvoir intervenir dessus. Après le bloc de filtre et la boucle pour mes custom post type, je replace donc un the_content(), ce qui va lui permettre d’éditer la page via l’éditeur classique de wordpress, ou tout autre page builder.
<?php /** * Template Name: Toutes nos Formations * * @link https://developer.wordpress.org/themes/basics/template-hierarchy/
* */ get_header(); ?>
<div id="primary" class="content-area"> <main id="main" class="site-main"> <div class="flex-container"> <div class="flex-row"> <header class="page-header"> <h1 class="archive_title"><?php // Ici je ramène deux champs additionnels crées avec ACF, afin de laisser l'utilisateur indiquer un titre et une description personnalisée à mon modèle de page if(get_field('titre')) { echo '<p>' . get_field('titre') . '</p>'; } ?> </h1> <h2> <?php if(get_field('description')){ echo '<p>' . get_field('description') . '</p>'; } ?> </h2>
</header><!-- .page-header --> </div> <div class="flex-row"> <?php // Voici le formulaire de filtrage. On boucle directement sur les taxonomie de mon custom post type ?> <form action="#" method="POST" id="formation_filters"> <p><input type="radio" value="all" id="all" class="category_filter" name="category_formation_filters"><label for="all">Toutes</label></p>
<?php if( $terms = get_terms( array( 'taxonomy' => 'categories-formations' ) ) ) : foreach( $terms as $term ) : echo '<p><input type="radio" id="' . $term->term_id . '" value="' . $term->term_id . '" name="category_formation_filters" class="category_formation_filters"/><label for="' . $term->term_id. '">' . $term->name . '</label></p>'; endforeach; endif; ?> <!-- required hidden field for admin-ajax.php --> <input type="hidden" name="action" value="ccformationfilter" /> </form> </div> <?php // ma boucle qui me ramène tous les custom post type "formation" $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; $args=array( 'post_type' =>'formation', 'posts_per_page' =>5, 'paged' => $paged
<?php endwhile; ?> </div> <!-- end isotope-list -->
<?php
if ( $query->max_num_pages > 1 ) : echo '<div class="loadmore_block"><div id="cc_formation_loadmore">Afficher plus de formations</div></div>'; // you can use <a> as well endif;
<?php // hack : je replace ici the content(), pour laisser l'utilisateur administrer cette partie de la page
if ( have_posts() ) : while ( have_posts() ) : the_post(); the_content(); endwhile; endif; ;?> </main><!-- #main --> </div><!-- #primary --> <?php // les variables qui vont servir l'ajax ?> <script> var posts_myajax = '<?php echo serialize( $query->query_vars ) ?>', current_page_myajax = 1, max_page_myajax = <?php echo $query->max_num_pages ?> </script> <script src="<?php bloginfo('template_url')?>/js/load-more.js"></script> <?php get_footer();?>
Ici, il faut faire attention aux éléments suivants :
L’id du formulaire : #formation_filters
Le nom du bouton radio qui va nous permettre de récupérer la sélection de l’utilisateur : name= »category_formation_filters »
La valeur du champ caché pour l’envoi du formulaire : value= »ccformationfilter » qui devra correspondre au nom de mon action ajax pour les filtres.
Contrairement au précédent article, les variables servant wp_localize_script ne sont pas injectés via le fichier functions.php, mais directement à la fin de mon fichier page-formation.php. Ce sont ces variables qui seront utilisées dans le fichier js, donc attention à la nomenclature !
L’appel au fichier js qui va contenir tout le code est aussi appelé directement depuis cette page.
Ce fichier va contenir deux grandes fonctions et deux boucles, l’une pour les filtres, l’autre pour le bouton ajax load more. On reprend la même logique que pour les articles de blogs de mon précédent article, mais on sépare à présent les fichiers pour une arborescence plus propre, et un code plus facilement maintenable.
Juste en dessous, je crée une deuxième boucle qui me ramène les articles de la catégorie sélectionnée par l’utilisateur
$args['tax_query'] = array( array(.....
'terms' => $_POST['category_formation_filters'],
Le fichier js
Comme je l’ai indiqué plus haut, on doit faire appel à un nouveau fichier js que j’ai appelé load-more.js
A l’intérieur, on va créer nos deux fonctions, pour les filtres et le bouton load more.
jQuery(function($){
/* LOAD MORE FUNCTION ON FORMATION ARCHIVE PAGE */ $('#cc_formation_loadmore').click(function(){ data = { 'action': 'loadmoreformationbutton', // le nom de mon action ajax 'query': posts_myajax, // ma variable attribuée dans le fichier page-formation.php 'page' : current_page_myajax // ma variable attribuée dans le fichier page-formation.php }; $.ajax({ url : '/monsite/wp-admin/admin-ajax.php', // AJAX handler data : data, type : 'POST', beforeSend : function ( xhr ) { $('#cc_formation_loadmore').text('Recherche...'); // ici l'ID de mon bouton load more }, success : function( posts ){ if( posts ) {
$('#cc_formation_loadmore').text( 'Afficher plus de formations' ); $('#cc_formation_wrap').append( posts ); current_page_myajax++;
if ( current_page_myajax == max_page_myajax ) $('#cc_formation_loadmore').hide();
/* FILTERING FUNCTION ON FORMATION ARCHIVE PAGE */ $('#formation_filters').change(function(){ $.ajax({ url : '/numgrade/wp-admin/admin-ajax.php', data : $('#formation_filters').serialize(), // form data dataType : 'json', type : 'POST',
Pour que le tout fonctionne, il faut surtout bien faire attention à nommer les éléments de la même manière d’une page à l’autre.
Les différents ID et nom attribués dans les autres fichiers se retrouvent dans le js:
L’ID du conteneur principal : #cc_formation_wrap
L’ID de mon bouton load more : #cc_formation_loadmore
Le nom de mon action ajax : loadmoreformationbutton
L’ID de mon formulaire de filtrage : #formation_filters
mes variables crées dans le fichier page-formation.php : current_page_myajax , posts_myajax et max_page_myajax.
Recommandations :
Si malgré tout ce code vous ne parvenez pas à faire marcher le bouton loadmore en ajax ou le système de filtres, je vous invite à consulter les nombreux commentaires sur les pages suivantes : loadmore, filters, ajax et filtres, load more et pagination. De nombreux internautes posent des questions et d’autres y répondent. Vous devriez y trouver des pistes !
Si vous rencontrez un problème lors de l’affichage des articles, notamment au niveau du nombre de posts affichés, changez le paramètre « posts_per_page » et modifiez également les options dans le backoffice de wordpress dans Réglages / Lecture.