• Andry

    (@blackstar1991)


    I have a custom post type “news” that is formed as follows

    add_action('init', function () {
    
        $labels = array(
            'name' => 'News',
            'singular_name' => 'News',
            'add_new' => 'Add News',
            'add_new_item' => 'Add News',
            'edit_item' => 'Corrected news',
            'new_item' => 'New news',
            'all_items' => 'All news',
            'search_items' => 'Search news',
            'not_found' => 'News in these types were not found',
            'not_found_in_trash' => 'No such news were found in the basket',
            'menu_name' => 'News'
        );
    
        $args = array(
            'labels' => $labels,
            'public' => true,
            'publicly_queryable' => false,
            'menu_icon' => 'dashicons-email-alt2',
            'menu_position' => 5,
            'supports' => array('title', 'editor', 'custom-fields', 'thumbnail'),
            'taxonomies' => array('category', 'post_tag'),
    
            'hierarchical' => true,
            'has_archive'   => true,
            'query_var' => 'new',
            'rewrite' => array(
                'slug' => 'new',
            ),
        );
    
        register_post_type('news', $args);
    });

    It is necessary to make a filter some of chosen news.

    The filter must work without reloading the page, and pagination must be present (no more than 5 records per page). functipn.php

    add_action('wp_ajax_myfilter', 'my_filter_function');
    add_action('wp_ajax_nopriv_myfilter', 'my_filter_function');
    
    function my_filter_function(){
    
        $my_terms = $_POST['filter_tags_id'];
    
        if(!empty( $my_terms)){
            $args = array(
                'post_type' => 'news',
                'orderby' => 'post_date',
                'order' => 'DESC',
                'posts_per_page' => '5',
                'tax_query' => [
                    'relation' => 'OR',
                    [
                        'taxonomy' => 'post_tag',
                        'field'    => 'id',
                        'terms'    => $my_terms,
                    ]
                ],
            );
        } else{
            $args = array(
                'post_type' => 'news',
                'orderby' => 'post_date',
                'order' => 'DESC',
                'posts_per_page' => -1,
            );
        }
    
        $query = new WP_Query( $args );
        if( $query->have_posts() ) :
            while ($query->have_posts()) : $query->the_post();
                $title = get_the_title();
    
                $publication_arr = get_post_custom_values('publication_img');
    
                if (is_null($publication_arr) || $publication_arr[0] == '0') {
                    $publication_img_src = get_template_directory_uri() . '/images/no-image.jpg';
                } else {
                    $publication_img_src = '';
                }
                echo '<div class="block_item">
                        <img class="block_item__img" src="' . $publication_img_src . '" alt="' . $title . '">
                        <a class="block_item__link" href="' . get_permalink() . '">' . $title . '</a>
                  </div>';
            endwhile;
            ?>
            <div class="category_pagination">
                            <?php
                            echo paginate_links( array(
                                'base' => get_pagenum_link(1) . '%_%',
                                'format' => 'page/%#%/',
                                'total' => $query->max_num_pages,
                                'current' => max( 1, get_query_var('paged') ),
                                'show_all' => false,
                                'end_size' => 1,
                                'mid_size' => 2,
                                'prev_next' => true,
                                'prev_text' => __('Previous', 'test'),
                                'next_text' => __('Next', 'test'),
                                'class' => '',
                            ) );
                            ?>
                        </div>
            <?php
            wp_reset_postdata();
        else :
            echo '<div class="block_item">No news found</div>';
    
        endif;
    
        die();
    }

    I made a page with filtering, but there is a problem with pagination. Pagination for filters does not work. The pagination links look like this.

    <a class="page-numbers" >2</a>

    How to fix this problem with pugination?

Viewing 5 replies - 1 through 5 (of 5 total)
  • Moderator bcworkz

    (@bcworkz)

    With Ajax URLs you cannot use the usual 'page/%#%/' format in paginate_links(). The eventual Ajax URL should look more like admin-ajax.php?paged=2

    With a typical non-Ajax pagination link, WP can parse the URL and get its paged query var from /page/2/ on its own. With Ajax, WP_Query needs some help. Get the passed paged query value from $_GET[‘paged’]. Validate the passed value to ensure it’s a simple integer, then assign the value as a WP_Query “paged” arg.

    Thread Starter Andry

    (@blackstar1991)

    Hmm, sounds complicated. Perhaps there is more information on what this Ajax filter should look like? * It does not matter how the URL will look like for pagination of the selected news by the filter

    Moderator bcworkz

    (@bcworkz)

    The solution in code is often much simpler than explaining what to do ??

    I’m not aware of any docs that fully describe this specific situation. You could try general ‘net searching for “wordpress ajax pagination” to find reasonable examples, but you’d likely need to wade through a lot of cruft to find something.

    Break down any problem into small parts and address each individually. It’ll all come together in the end. If you’ve managed to get basic Ajax working (I’m assuming), this should be even easier.

    1. Change paginate_links() format arg to ?paged=%#% to get the desired page passed as an Ajax URL query string.

    2. Add 'paged' => (int) $_REQUEST['paged'],* to the WP_Query args. Type casting a value with (int) is adequate sanitation for this usage.

    That’s all! Two code changes should get pagination working. Your filter may have other issues you’ll need to address, but that’s all you need to get a requested page’s worth of content. I’m assuming you already have JavaScript/jQuery listeners on the paginated links that fire when any of them are clicked.

    *I’m not sure how the paginated links get used as an Ajax request, so I decided $_REQUEST would be a better way to get the passed value instead of the $_GET I suggested earlier.

    Thread Starter Andry

    (@blackstar1991)

    Thanks for the advice. Unfortunately this didn’t solve the problem. When I click on the link of the 2nd page of filtered posts, I get 0.

    It’s my new functions.php

    <?php
    
    add_action('wp_enqueue_scripts', function () {
        wp_enqueue_style('main_css', get_template_directory_uri() . '/css/new-styles.css', '', null, false);
        wp_enqueue_script('main_js', get_template_directory_uri() . '/js/scripts.js', array('jquery'), null, true);
    
    
    });
    
    add_action('init', function () {
    
        $labels = array(
            'name' => 'News',
            'singular_name' => 'News',
            'add_new' => 'Add News',
            'add_new_item' => 'Add News',
            'edit_item' => 'Corrected news',
            'new_item' => 'New news',
            'all_items' => 'All news',
            'search_items' => 'Search news',
            'not_found' => 'News in these types were not found',
            'not_found_in_trash' => 'No such news were found in the basket',
            'menu_name' => 'News'
        );
    
        $args = array(
            'labels' => $labels,
            'public' => true,
            'publicly_queryable' => false,
            'menu_icon' => 'dashicons-email-alt2',
            'menu_position' => 5,
            'supports' => array('title', 'editor', 'custom-fields', 'thumbnail'),
            'taxonomies' => array('category', 'post_tag'),
    
            'hierarchical' => true,
            'has_archive'   => true,
            'query_var' => 'new',
            'rewrite' => array(
                'slug' => 'new',
            ),
        );
        register_post_type('news', $args);
    });
    
    add_action('wp_ajax_myfilter', 'my_filter_function');
    add_action('wp_ajax_nopriv_myfilter', 'my_filter_function');
    
    function my_filter_function(){
    
        $my_terms = $_POST['filter_tags_id'];
    
        if(!empty( $my_terms)){
            $args = array(
                'post_type' => 'news',
                'orderby' => 'post_date',
                'order' => 'DESC',
                'posts_per_page' => '5',
                'tax_query' => [
                    'relation' => 'OR',
                    [
                        'taxonomy' => 'post_tag',
                        'field'    => 'id',
                        'terms'    => $my_terms,
                    ]
                ],
            );
        } else{
            $args = array(
                'post_type' => 'news',
                'orderby' => 'post_date',
                'order' => 'DESC',
                'posts_per_page' => -1,
            );
        }
        $query = new WP_Query( $args );
        if( $query->have_posts() ) :
            while ($query->have_posts()) : $query->the_post();
                $title = get_the_title();
                echo '<div class="block_item">
                        <a class="block_item__link" href="' . get_permalink() . '">' . $title . '</a>
                  </div>';
            endwhile;
            ?>
            <div class="category_pagination">
                            <?php
    
                            echo paginate_links( array(
                                'base' => get_pagenum_link(1) . '%_%',
                                'format' => '?paged=%#%',
                                'paged' => (int) $_REQUEST['paged'],
                                'total' => $query->max_num_pages,
                                'current' => max( 1, get_query_var('paged') ),
                                'show_all' => false,
                                'end_size' => 1,
                                'mid_size' => 2,
                                'prev_next' => true,
                                'prev_text' => __('Previous', 'test'),
                                'next_text' => __('Next', 'test'),
                                'class' => '',
                            ) );
                            ?>
                        </div>
            <?php
            wp_reset_postdata();
        else :
            echo '<div class="block_item">No news found</div>';
        endif;
        die();
    }
    

    The file scripts.js looks like

    jQuery(function(n){
        const $ = jQuery;
        const filter = $('#filter');
        
        $(".btn_clearFilters").on("click", function (){
            filter.find('input').prop( "checked", false );
            $(".button-filter").click();
        })
        
            filter.submit(function(){
    
                $.ajax({
                    url:filter.attr('action'),
                    data:filter.serialize(), // form data
                    type:filter.attr('method'), // POST
                    beforeSend:function(xhr){
                        filter.find('.button-filter').text('Processing...');
                    },
                    success:function(data){
                        filter.find('.button-filter').text('Apply filter');
                        $('#response').html(data);
                    }
                });
                return false
            });
      
    });

    and page with this news page-all-news.php

    <?php get_header(); ?>
        <h1><?php the_title() ?></h1>
        <main  class="main_wrapper" id="page-news">
            <div class="section">
                <div class="block_filters">
                    <p class="block_filters__title"><?php _e("Filters") ?></p>
                    <form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter" class="filters_box">
                        <input type="hidden" name="action" value="myfilter">
                        <ul class="filters_list">
                            <?php $cur_terms =  get_terms( array(
                                'taxonomy' => 'post_tag',
                                'hide_empty' => false,
                            ) );
                            if (is_array($cur_terms)) {
                                foreach ($cur_terms as $cur_term) {
                                    echo '<li class="filters_item"><label class="filters_el"><input type="checkbox" name="filter_tags_id[]" value="'. $cur_term->term_id .'"><span>' . $cur_term->name . '</span></label></li>';
                                }
                            } ?>
                            <li class="filters_item"><button class="btn_clearFilters" type="button">Clear<br>All Filters</button></li>
                            <li class="filters_item"><button class="button-filter">Apply filter</button></li>
                        </ul>
                    </form>
                </div>
    
                <?php if (have_posts()) : ?>
                <div id="response" class="block_list">
                    <?php
                    $current = absint(
                        max(
                            1,
                            get_query_var( 'paged' ) ? get_query_var( 'paged' ) : get_query_var( 'news' )
                        )
                    );
                    $query = new WP_Query(
                        [
                            'post_type' => 'news',
                            'posts_per_page' => -1,
                            'paged' => $current,
                        ]
                    );
    
                    if ($query->have_posts()) {
                        while ($query->have_posts()) : $query->the_post();
                            $title = get_the_title();
    
                            $publication_arr = get_post_custom_values('publication_img');
    
                            if (is_null($publication_arr) || $publication_arr[0] == '0') {
                                $publication_img_src = get_template_directory_uri() . '/images/no-image.jpg';
                            } else {
                                $publication_img_src = '';
                            }
    
                            echo '<div class="block_item">
                                    <img class="block_item__img" src="' . $publication_img_src . '" alt="' . $title . '">
                                    <a class="block_item__link" href="' . get_permalink() . '">' . $title . '</a>
                                 </div>';
                        endwhile; ?>
    
    
    
                    <?php }
                    wp_reset_postdata(); ?>
    
                    <?php else : ?><p><?php esc_html_e('Missing posts with defined criteria', 'test'); ?></p><?php endif; ?>
                </div>
    
            </div>
        </main>
    <?php get_footer();

    Maybe you have some others tips, why ajax pagination doesn’t give right content?

    Moderator bcworkz

    (@bcworkz)

    Why is an Ajax URL appearing in your browser address bar? A proper Ajax request shouldn’t appear there. You may need to event.preventDefault(); on the submit button’s click event.

    Once the default is prevented, your jQuery needs to somehow ensure the paged arg gets to the server. It either needs to be appended to the Ajax request URL or included in the form’s hidden field named “paged”.

    Whatever you’re doing to listen for a submit button click event, you also need to be doing for the links output by paginate_links().

Viewing 5 replies - 1 through 5 (of 5 total)
  • The topic ‘Pagination for aJax filters’ is closed to new replies.