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>]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
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
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
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
_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
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();
}