Cum să filtrezi datele postărilor cu AJAX în pagină?

21 nov. 2014, 15:34:36
Vizualizări: 19.9K
Voturi: 3

Am creat un tip de postare personalizat "Work items" pentru a introduce elementele din portofoliul meu personal. "Work items" au taxonomii precum "Graphics", "Websites" etc.

Pot să le afișez pe toate într-un șablon archive-work.php, dar vreau să le filtrez în pagină cu AJAX. Am urmat acest exemplu: http://www.bobz.co/ajax-filter-posts-tag/

Mă confrunt cu următoarea problemă:

  • La prima încărcare a paginii, nu se aduce nimic din taxonomiile tipului meu de postare personalizat. Dacă dau click pe unul dintre link-uri, datele sunt actualizate cu succes. Problema apare doar la prima încărcare a paginii. Bănuiesc că nonce-ul nu este verificat pentru că nu este trimis prin POST și astfel eșuează.

Poate cineva să-mi spună unde am greșit?

functions.php

function ajax_filter_posts_scripts() {
  // Înregistrare script
  wp_register_script('afp_script', get_template_directory_uri() . 
      '/ajax-work-items.js', false, null, false);
  wp_enqueue_script('afp_script');

  wp_localize_script( 'afp_script', 'afp_vars', array(
        'afp_nonce' => wp_create_nonce( 'afp_nonce' ), // Creează nonce pe care îl vom folosi mai târziu pentru verificarea cererii AJAX
        'afp_ajax_url' => admin_url( 'admin-ajax.php' ),
      )
  );
}
add_action('wp_enqueue_scripts', 'ajax_filter_posts_scripts', 100);

$result = array();

// Script pentru obținerea postărilor
function ajax_filter_get_posts( $work_item ) {

  // Verifică nonce
  if( !isset( $_POST['afp_nonce'] ) || 
      !wp_verify_nonce( $_POST['afp_nonce'], 'afp_nonce' ))
    die('Permisiune refuzată');

  $work_item = $_POST['stuff'];

  // WP Query
  $args = array(
    'stuff' => $work_item,
    'post_type' => 'work',
    'posts_per_page' => -1,
  );

  // Dacă taxonomia nu este setată, elimină cheia din array și obține toate postările
  if( !$work_item ) {
    unset( $args['stuff'] );
  }

  $query = new WP_Query( $args );

  if ( $query->have_posts() ) : 
       while ( $query->have_posts() ) : 
       $query->the_post(); 

       $res = '<div class="col-lg-4">'.
                  '<a href="'.get_permalink().'">'.
                      '<article class="panel panel-default" id="post-'.get_the_id().'">'.
                          '<div class="panel-body">'.
                              get_the_post_thumbnail().
                              '<div class="panel-cover">'.
                                  '<h3>'.get_the_title().'</h3>'.
                                      get_the_content().
                              '</div>'.
                          '</div>'.      
                      '</article>'.
                  '</a>' .     
              '</div>';


       $result['response'][] = $res;
       $result['status'] = 'success';

   endwhile;
   else:
       $result['response'] = '<h2>Nu s-au găsit postări</h2>';
       $result['status']   = '404';
   endif;

   $result = json_encode($result);
   echo $result;

  die();
}

add_action('wp_ajax_filter_posts', 'ajax_filter_get_posts');
add_action('wp_ajax_nopriv_filter_posts', 'ajax_filter_get_posts');

//Obține filtrele de lucru
function get_work_filters()
{
    $work_items = get_terms('stuff');
    $filters_html = false;
    $count = count( $work_items );

    if( $count > 0 ):
        foreach( $work_items as $work_item )
        {
            $work_item_id = $work_item->term_id;
            $work_item_name = $work_item->name;

            $filters_html .= '<a href="' . 
                get_term_link( $work_item ) . 
                '" class="btn work-filter" title="' . 
                $work_item->slug . '">' . $work_item->name . '</a> ';
        }
        echo $filters_html;
    endif;
}

ajax-work-items.js

$(document).ready(function(){

    // filtre pentru lucrări

    $('.work-filter').click( function(event) {

        // Previne acțiunea implicită - deschiderea paginii cu etichete
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }

        // Obține slug-ul etichetei din atributul title
        var stuff = $(this).attr('title');        

        data = {
            action: 'filter_posts', // funcția de executat
            afp_nonce: afp_vars.afp_nonce, // wp_nonce
            post_type: "work", // eticheta selectată
            stuff: stuff,
            };

        $.ajax({ 
            type: "post",
            dataType: "json",
            url: afp_vars.afp_ajax_url, 
            data: data, 
            success: function(data, textStatus, XMLHttpRequest) {
                console.log(data);
                // Restaurează vizibilitatea div-ului
                $('.work-results').fadeOut()
                    .queue(function(n) {
                            $(this).html(data.response);
                            n();
                }).fadeIn();
            },
            error: function( XMLHttpRequest, textStatus, errorThrown ) {
                /*console.log( MLHttpRequest );
                console.log( textStatus );
                console.log( errorThrown );*/
                $('.work-results').fadeOut()
                    .queue(function(n) {
                            $(this).html("Nu s-au găsit elemente. ");
                            n();
                }).fadeIn();
            }
        });
    });

});

archive-work.php

<?php get_header(); ?>

<div id="workwrapper">  
    <div class="row-bg-page">
        <div class="container">
            <div class="jumbotron">
                <h1>Lucrările noastre</h1>
                <p class="lead">Oferim servicii profesionale ...
                </p>
            </div>
        </div>
    </div>
    <div class="row-bg-white">
        <div class="container">

            <div id="work-filter" class="text-center">
                <?php get_work_filters(); ?>
            </div>
            <br />

            <div class="work-results">
                <?php ajax_filter_get_posts(""); ?>
            </div>

        </div>
    </div>

</div>

<?php get_footer(); ?>
0
Toate răspunsurile la întrebare 1
0

După cum probabil ați ghicit, asta se întâmplă (cel puțin așa cred).

Ar trebui să separați logica pentru Ajax de logica pentru "încărcarea inițială". Puteți crea o funcție, de exemplu my_get_posts, care va fi apelată în archive-work.php și apoi în ajax_filter_get_posts puteți apela funcția my_get_posts().

archive-work.php

    <div class="work-results">
                    <?php $res = my_get_posts();
                 echo $res['response'];
?>
                </div>

functions.php

    function ajax_filter_get_posts( $work_item ) {

      // Verifică nonce
      if( !isset( $_POST['afp_nonce'] ) || 
          !wp_verify_nonce( $_POST['afp_nonce'], 'afp_nonce' ))
        die('Permission denied');

         $work_item = $_POST['stuff'];
         $result = json_encode(my_get_posts($work_item, true));
         echo $result;

         die();

    }

function my_get_posts($work_item = '', $ajax = false){

    // WP Query
      $args = array(
        'stuff' => $work_item,
        'post_type' => 'work',
        'posts_per_page' => -1,
      );

      // Dacă taxonomia nu este setată, elimină cheia din array și obține toate postările
      if( !$work_item ) {
        unset( $args['stuff'] );
      }

      $query = new WP_Query( $args );
      $html = '';
      $items = array();

      if ( $query->have_posts() ) : 
           while ( $query->have_posts() ) : 
           $query->the_post(); 

           $res = '<div class="col-lg-4">'.
                      '<a href="'.get_permalink().'">'.
                          '<article class="panel panel-default" id="post-'.get_the_id().'">'.
                              '<div class="panel-body">'.
                                  get_the_post_thumbnail().
                                  '<div class="panel-cover">'.
                                      '<h3>'.get_the_title().'</h3>'.
                                          get_the_content().
                                  '</div>'.
                              '</div>'.      
                          '</article>'.
                      '</a>' .     
                  '</div>';


           $ajax ? $items[] = $res : $html .= $res;


       endwhile;

       $result['response'] = $ajax ? $items : $html;
       $result['status'] = 'success';

       else:
           $result['response'] = '<h2>Nu s-au găsit postări</h2>';
           $result['status']   = '404';
       endif;
wp_reset_postdata();
return $result;
}

De asemenea, nu cred că următorul cod este necesar, deoarece WordPress se va ocupa de asta.

// Dacă taxonomia nu este setată, elimină cheia din array și obține toate postările
          if( !$work_item ) {
            unset( $args['stuff'] );
          }

Codul este o schiță și ar putea fi îmbunătățit, dar înțelegeți ideea. Nu l-am testat, dar ar trebui să funcționeze.

EDIT

Nu uitați să apelați wp_reset_postdata(); după fiecare WP_Query personalizat pentru a restaura variabila globală $post. Mai multe detalii aici: http://codex.wordpress.org/Function_Reference/wp_reset_postdata

21 nov. 2014 16:48:59