Volver

Cómo crear un filtro Ajax Word Press

Con el siguiente instructivo veremos cómo crear interacción con un filtro en tiempo real con Ajax en wordpress.

 

1. Lo primero que debes hacer es escoger la zona o el elemento que va a actualizarse, en este ejemplo el elemento con el que trabajaremos tiene el ID de

<div id=”searcher-post-answers” class=”pt-3″>
<div id="searcher-post-answers" class="pt-3">
</div>]

2. Luego de esto debemos crear un formulario, el cual va a tener los datos que se van a consultar. De este formulario debemos tener muy presente, la propiedad action=”<?php echo site_url() ?>/wp-admin/admin-ajax.php”, ya que, esta contiene la dirección de la API que procesará nuestra petición de ajax. También  debemos tener el input que va a ejecutar la petición <i class=”fas fa-search” id=”header-search-icon” data-bs-dismiss=”modal” aria-label=”Close”></i>, este botón debe tener las propiedades de name:action  y value  que debe tener el nombre de función que más adelante se mostrará.

<div class="main-menu__nav-search">
  <div class="main-menu__nav-search-wrapper d-flex justify-content-end align-items-center">
    <i id="button-close" class="fa-regular fa-circle-xmark" data-bs-dismiss="modal" aria-label="Close"></i>
    <form class="from main-menu__search" action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" class="filter-posts" method="POST" id="formFilterHeader">
      <input autofocus size="80" maxlength="80" minlength="1" id="searcher" class="mn" type="text" name="the-text" placeholder="<?php echo 'Busca artículos por palabras claves' ?>">
      <input type="hidden" name="action" value="searcherPosts">
    </form>
    <i class="fas fa-search" id="header-search-icon" data-bs-dismiss="modal" aria-label="Close"></i>
  </div>
</div>

3. Vamos a crear una función con los hook  de acction, se crean dos llamadas a hook, ya que una es para los usuarios registrados y el otro para usuarios no registrados y esto lo asociamos a un funcion en este ejemplo al funcion se llama searcherPosts.

add_action('wp_ajax_nopriv_searcherPosts', 'searcherPosts');
add_action('wp_ajax_searcherPosts', 'searcherPosts');

4. Luego creamos la función y en esta validamos el elemento $POST, este contiene la información de los input del formulario enviado.

5. Para obtener la información de un campo concreto hacemos lo siguiente, con la propiedad name del input del cual queremos obtener la usamos para obtenerala $_POST[‘the-text’]

6. Ya teniendo la función correctamente, vamos a crear la interacción para llamar a la API con Javascript.

7. El primer archivo es _api-calls.js, el cual se encargará de hacer todo el proceso de llamada a la api Ajax.

8. Por último tenemos el archivo del componente, donde colocamos la interacción de los elementos del formulario, lo más relevante es la función de reset que vuelve el componente a su estado inicial y la función enviar que se encarga de llamar a la API.

Archivos Usados

1.

Elemento donde se muestra la info

PHP

No definido

Block

<div id="searcher-post-answers" class="pt-3">
</div>]

2.

Formulario

PHP

No definido

Block

<div class="main-menu__nav-search">
  <div class="main-menu__nav-search-wrapper d-flex justify-content-end align-items-center">
    <i id="button-close" class="fa-regular fa-circle-xmark" data-bs-dismiss="modal" aria-label="Close"></i>
    <form class="from main-menu__search" action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" class="filter-posts" method="POST" id="formFilterHeader">
      <input autofocus size="80" maxlength="80" minlength="1" id="searcher" class="mn" type="text" name="the-text" placeholder="<?php echo 'Busca artículos por palabras claves' ?>">
      <input type="hidden" name="action" value="searcherPosts">
    </form>
    <i class="fas fa-search" id="header-search-icon" data-bs-dismiss="modal" aria-label="Close"></i>
  </div>
</div>

 

3.

ajax-searcher-posts.php

PHP

functions/utils/

Block

<?php
/***
 *  Ajax logic for posts response
 *
 */

add_action('wp_ajax_nopriv_searcherPosts', 'searcherPosts');
add_action('wp_ajax_searcherPosts', 'searcherPosts');

function searcherPosts()
{
  if ($_POST):
    // Variable array of posts
    $wpost_keyword = $_POST['the-text'];

    $args = [
      'orderby' => 'date',
      'order' => 'DESC',
      'post_type' => 'any',
      'post_status' => 'publish',
      'posts_per_page' => -1,
      's' => $wpost_keyword,
    ];

    // Post type query
    $query = new WP_Query($args);
    if ($query->have_posts()): ?>
      <section class="posts-category post-answers reset-transition" id="posts-category">
        <div class="container">
          <header class="post-answers__title">
            <h2>
              <?php echo 'Resultados' ?>
            </h2>
            <div class="d-flex mb-3">
              <div class="post-answers__return button-primary">
                <i class="post-answers__return-icon">← </i>
                <span class="post-answers__return-text">
                  <?php echo 'Volver' ?>
                </span>
              </div>
            </div>
          </header>
          <div id="postsCategory" class="row posts-category__container justify-content-center">
            <?php
            while ($query->have_posts()):
              $query->the_post();
              get_template_part('cards/post-card');
              ?>
            <?php endwhile; ?>
            <div class="pagination">
              <?php echo paginate_links(array('total' => $query->max_num_pages)); ?>
            </div>
          </div>
        </div>
      </section>
      <?php
      wp_reset_postdata();
    else: ?>
      <section class="posts-category post-answers" id="posts-category">
        <div class="container">
          <header class="post-answers__title mb-4">
            <h2 class="h1">
              Resultado no encontrado
            </h2>
          </header>
          <h3 class="post-answers__message highlight mb-4">Te sugerimos que cambies tus términos de búsqueda y uses palabras
            claves
            del tema que deseas buscar.</h3>
          <div class="post-answers__return my-4 d-flex">
            <span class="post-answers__return-text button-primary">
              Volver
            </span>
          </div>
        </div>
      </section>
      <?php
    endif;
  endif;
  wp_die();
}

 

4.

_api-calls.js

JavaScript

frontend/js/api/

Block

import { serialize } from "../libraries/utils";

class FetchAPI {
  constructor(wrapper, resultWrapper) {
    this.wrapper = wrapper;
    this.resultsDOM = resultWrapper;

    this.TYPES_SCRIP
    this.fetchResponse();
  }

  fetchResponse() {
    const serializedFrm = serialize(this.wrapper);
    const ajaxUrl = this.wrapper.getAttribute("action");
    const resultsDiv = this.resultsDOM;

    const paramsObj = {
      method: "POST",
      credentials: "same-origin",
      headers: new Headers({
        "Content-Type": "application/x-www-form-urlencoded",
      }),
      body: serializedFrm,
    };

    fetch(ajaxUrl, paramsObj)
      .then((response) => response.text())
      .then((data) => {
        if (data) {
          resultsDiv.innerHTML = data;
        }
      })
      .catch((e) => console.log("error", e));
  }
}

export { FetchAPI };

 

5.

searcher-posts.js

JavaScript

frontend/js/components/

Block

import { FetchAPI } from "../api/_api-calls";
import { viewTransition } from "../api/_api_view-transition";

const $postsFilterForm = document.getElementById("formFilterHeader");
const $postsResults = document.getElementById("searcher-post-answers");
const $searcher = document.getElementById("searcher");
let executedFilter = false;


// Fetch filters module
document.addEventListener("submit", (e) => {
  if (e.target.matches("#formFilterHeader")) {
    e.preventDefault();
    enviar();
  }
});

//from keypress
document.addEventListener("click", (e) => {
  if (e.target.matches("#header-search-icon")) {
    if($('#searcher').val()) {
        enviar();
    }
  }

  if (
    e.target.matches(".post-answers__return") ||
    e.target.matches(".post-answers__return-icon") ||
    e.target.matches(".post-answers__return-text")
  ) {
    reset();
  }
});

//Presionar enter
document.addEventListener("keypress", (e) => {
  if (e.target.matches("#searcher") && e.target.keyCode === 13) {
    $('body').removeClass('modal-open');
    enviar();
  }
});

//Al borrar el contenido
document.addEventListener("keydown", (e) => {
  if (e.key === "Backspace" || e.key === "Delete") {
    if (executedFilter && $searcher.value.length <= 1) {
      reset();
    }
  }
});

document.addEventListener("click", (e) => {
  if (e.target.matches('#header-search-icon')) {
    $('.main-menu__nav-search').addClass('active');
    $('#searcher').focus();
  }
});


document.addEventListener("click", (e) => {

  if($('.main-menu__nav-search').hasClass('active')){
    if (
        !e.target.matches('#searcher') &&
        !e.target.matches('#header-search-icon') &&
        !e.target.matches('.main-menu__nav-search')
      ) {
        viewTransition('exit-right', $('.main-menu__nav-search-wrapper'), () =>{
          $('.main-menu__nav-search').removeClass('active');
          $('#searcher').focus();
        })
    }
  }

  if(e.target.matches('#button-close')){
    viewTransition('exit-right', $('.main-menu__nav-search-wrapper'), () =>{
      $('.main-menu__nav-search').removeClass('active');
      $('#searcher').val('');
    })
  }
});


//functions
function reset() {
  executedFilter = false;
  window.location.reload();
}

function enviar() {
  if ($searcher.value) {
    $(window).scrollTop(0);
    executedFilter = true;
    const createFilters = new FetchAPI($postsFilterForm, $postsResults);
  } else reset();
}

 

Avatar

Autor

Elan Francisco P. Asprilla
Desarrollador Frontend

Artículos relacionados

useReducer en React: Guía Completa

¿Qué es useReducer? useReducer es un Hook de...

Carrusel de logos (Palmas)

Este es un carousel(Carrusel) que muestra...

¿Qué son las vistas en Drupal?

En Drupal, las vistas (“Views”) son...

Placeholder Image

🧩 Problema de compatibilidad de Slick con Drupal 10.4.x

🔍 Contexto Durante el desarrollo de un sitio...