Come filtrare i dati dei post con AJAX nella pagina?

21 nov 2014, 15:34:36
Visualizzazioni: 19.9K
Voti: 3

Ho creato un custom post_type chiamato "Work items" per inserire elementi del mio portfolio personale. Gli "Work items" hanno tassonomie come "Grafica", "Siti Web" ecc.

Sono in grado di visualizzarli tutti in un template archive-work.php ma voglio filtrarli nella pagina con AJAX. Ho seguito questo esempio: http://www.bobz.co/ajax-filter-posts-tag/

Sto riscontrando un problema:

  • La prima volta che la pagina viene visualizzata, non viene recuperato nulla dalle tassonomie del mio custom post type. Se clicco su uno dei miei link, i dati vengono aggiornati con successo. Il problema si verifica solo al primo caricamento della pagina. Suppongo che il nonce non venga verificato perché non viene inviato con POST e quindi fallisce.

Qualcuno può dirmi dove ho commesso un errore?

functions.php

function ajax_filter_posts_scripts() {
  // Carica lo 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' ), // Crea nonce che useremo dopo per verificare la richiesta AJAX
        'afp_ajax_url' => admin_url( 'admin-ajax.php' ),
      )
  );
}
add_action('wp_enqueue_scripts', 'ajax_filter_posts_scripts', 100);

$result = array();

// Script per ottenere i post
function ajax_filter_get_posts( $work_item ) {

  // Verifica nonce
  if( !isset( $_POST['afp_nonce'] ) || 
      !wp_verify_nonce( $_POST['afp_nonce'], 'afp_nonce' ))
    die('Permesso negato');

  $work_item = $_POST['stuff'];

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

  // Se la tassonomia non è impostata, rimuovi la chiave dall'array e ottieni tutti i post
  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>Nessun post trovato</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');

//Ottieni Filtri Lavoro
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(){

    // filtri lavoro

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

        // Previeni azione predefinita - apertura pagina tag
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }

        // Ottieni slug del tag dall'attributo title
        var stuff = $(this).attr('title');        

        data = {
            action: 'filter_posts', // funzione da eseguire
            afp_nonce: afp_vars.afp_nonce, // wp_nonce
            post_type: "work", // tag selezionato
            stuff: stuff,
            };

        $.ajax({ 
            type: "post",
            dataType: "json",
            url: afp_vars.afp_ajax_url, 
            data: data, 
            success: function(data, textStatus, XMLHttpRequest) {
                console.log(data);
                // Ripristina visibilità div
                $('.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("Nessun elemento trovato. ");
                            n();
                }).fadeIn();
            }
        });
    });

});

archive-work.php

<?php get_header(); ?>

<div id="workwrapper">  
    <div class="row-bg-page">
        <div class="container">
            <div class="jumbotron">
                <h1>I nostri lavori</h1>
                <p class="lead">Forniamo servizi professionali ...
                </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
Tutte le risposte alla domanda 1
0

Come puoi immaginare, è quello che sta succedendo (almeno penso).

Dovresti separare la tua logica AJAX dalla logica del "primo caricamento". Puoi creare una funzione, ad esempio my_get_posts, che verrà chiamata all'interno di archive-work.php e poi all'interno di ajax_filter_get_posts puoi chiamare la funzione 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 ) {

      // Verifica il nonce
      if( !isset( $_POST['afp_nonce'] ) || 
          !wp_verify_nonce( $_POST['afp_nonce'], 'afp_nonce' ))
        die('Permesso negato');

         $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,
      );

      // Se la tassonomia non è impostata, rimuovi la chiave dall'array e ottieni tutti i post
      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>Nessun post trovato</h2>';
           $result['status']   = '404';
       endif;
wp_reset_postdata();
return $result;
}

Inoltre non penso che il seguente codice sia necessario poiché WordPress se ne occuperà automaticamente.

// Se la tassonomia non è impostata, rimuovi la chiave dall'array e ottieni tutti i post
          if( !$work_item ) {
            unset( $args['stuff'] );
          }

Il codice è una bozza e potrebbe essere migliorato ma hai capito l'idea. Non l'ho testato ma dovrebbe funzionare

MODIFICA

Non dimenticare di chiamare wp_reset_postdata(); dopo ogni WP_Query personalizzata per ripristinare la variabile globale $post. Maggiori informazioni qui: http://codex.wordpress.org/Function_Reference/wp_reset_postdata

21 nov 2014 16:48:59