ajaxurl no está definido en el front-end
Estoy tratando de crear un formulario ajax en el lado del front-end. Estoy usando el código
jQuery.ajax(
{
type: "post",
dataType: "json",
url: ajaxurl,
data: formData,
success: function(msg){
console.log(msg);
}
});
para el cual estoy obteniendo el error
Uncaught ReferenceError: ajaxurl is not defined worklorAjaxBookForm @
?page_id=2:291onclick @ ?page_id=2:202
Mientras que usar un código similar en el backend del administrador funciona. ¿Qué url debo usar para procesar la petición ajax?

En el backend hay una variable global ajaxurl
definida por WordPress.
Esta variable no es creada por WP en el frontend. Esto significa que si quieres usar llamadas AJAX en el frontend, entonces tienes que definir esta variable tú mismo.
Una buena forma de hacer esto es usando wp_localize_script
.
Supongamos que tus llamadas AJAX están en el archivo my-ajax-script.js
, entonces agrega wp_localize_script para este archivo JS así:
function my_enqueue() {
wp_enqueue_script( 'ajax-script', get_template_directory_uri() . '/js/my-ajax-script.js', array('jquery') );
wp_localize_script( 'ajax-script', 'my_ajax_object',
array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
}
add_action( 'wp_enqueue_scripts', 'my_enqueue' );
Después de localizar tu archivo JS, puedes usar el objeto my_ajax_object
en tu archivo JS:
jQuery.ajax(
{
type: "post",
dataType: "json",
url: my_ajax_object.ajax_url,
data: formData,
success: function(msg){
console.log(msg);
}
});

¿Puedo usar wp_localize_script
sin tener que usar wp_enqueue_scritp
?

Usas el handle del script en wp_localize_script, por lo que tienes que usar wp_enqueue_script para al menos uno de tus scripts. Pero... No usar wp_enqueue_script no es una buena idea (arriesgas tener conflictos y problemas de dependencias).

no tengo ningún script externo que cargar, solo quiero usar ajaxurl para hacer una llamada ajax. ¿no es posible?

¿Y dónde vas a poner esta llamada AJAX? ¿Como script en línea? Es una muy mala idea...

Tengo un formulario separado, en el que estoy manejando la validación y al enviar, una llamada AJAX para enviar el formulario, por supuesto, de la manera de WordPress agregando un hook. De todos modos ya encontré la forma de usar ajaxurl.

Increíble... Lo estoy usando en mi Javascript en el front-end y funciona de maravilla :)

No entiendo. ¿Qué pasa si las llamadas se hacen desde múltiples archivos separados? ¿Cómo procedes en ese caso? ¿No puedes simplemente "declarar" una única URL AJAX para toda la instancia de WP? ¿Y por qué no se hace eso automáticamente?

Para usar ajaxurl directamente, en tu archivo de plugin añade esto:
add_action('wp_head', 'myplugin_ajaxurl');
function myplugin_ajaxurl() {
echo '<script type="text/javascript">
var ajaxurl = "' . admin_url('admin-ajax.php') . '";
</script>';
}
Luego puedes usar ajaxurl
para peticiones AJAX.

Esta respuesta hace que ajaxurl
funcione de manera similar al uso predeterminado. Lo cual es mucho mejor que la respuesta aceptada.

@Jules ajaxurl
sigue estando disponible en un archivo *.js
. Para hacerlo, es posible que necesites declarar la variable ajaxurl
al principio de la carga de la página. Otra cosa a considerar es la llamada a tu archivo *.js
externo. El archivo externo debería llamarse DESPUÉS de que ajaxurl
haya sido instanciado y se le haya dado el valor de URL correcto.

¿Qué pasa con los conflictos con otros plugins o temas que declaran la variable de la misma manera? Creo que al menos deberías usar un namespace para la variable. De todos modos, pienso que la respuesta aceptada tiene menos potencial de causar problemas/conflictos más adelante. Pero supongo que si sabes bien lo que estás haciendo, este enfoque está bien.

La forma de hacerlo en 2021 es un poco diferente ;-)
function my_enqueue() {
wp_enqueue_script( 'ajax-script', get_template_directory_uri() . '/js/my-ajax-script.js', array('jquery') );
wp_add_inline_script( 'ajax-script',
'const myVariables = ' . json_encode(
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
) ),
'before' );
}
add_action( 'wp_enqueue_scripts', 'my_enqueue' );
Fuente: https://developer.wordpress.org/reference/functions/wp_add_inline_script/#comment-4632

Hoy me encontré con esta misma solución, hay más información sobre cuándo usar wp_add_inline_script()
frente a wp_localize_script()
en la documentación de wp_localize_script también, por si tienes curiosidad.

He utilizado el siguiente código en un sitio WordPress.
Podemos usar el siguiente código para configurar ajaxurl de esta manera.
<?php echo esc_url(admin_url('admin-ajax.php')); ?>
También he añadido un ejemplo de ajax donde podemos usar la línea anterior.
function setNotificationRead() {
fetch('<?php echo esc_url(admin_url('admin-ajax.php')); ?>', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
},
body: `action=yourFunctionsAction`,
credentials: 'same-origin'
}).then(response => {
return response.json();
}).then(data => {
if (data.status === 'true') {
console.log('Hacer algo...');
}
});
}

Logré que esto funcione después de muchas horas... y pruebas y errores. Así que, comparto cómo hacer que ajax funcione en WordPress con un ejemplo (comencé con https://www.tweaking4all.com/web-development/wordpress/wordpress-ajax-example/#comment-562814 y adapté el ejemplo)
--usa las herramientas de desarrollador de Chrome y desactiva la caché desde la pestaña de red --revisa la consola si obtienes algún error, el primer objetivo es ver "¡listo!" en la consola cuando hagas clic en el botón y si todo funciona, ¡también obtendrás una buena salida!
--agrega al sitio de WordPress como un bloque HTML personalizado:
<div id="receiving_div_id">
<p>No se ha cargado nada aún</p>
</div>
<button id="button_to_load_data">Obtener Contenido Ajax</button>
--agrega a theme/js/button.js (crea la carpeta js si no existe):
jQuery("#button_to_load_data").click(function() {
console.log( "¡listo!" );
var data = {
'action' : 't4a_ajax_call', // ¡el nombre de tu función PHP!
'function' : 'show_files', // un valor aleatorio que queremos pasar
'fileid' : '7' // otro valor aleatorio que queremos pasar
};
jQuery.post(my_ajax_object.ajax_url, data, function(response) {
jQuery("#receiving_div_id").html(response);
});
});
--agrega a functions.php del tema:
/* script personalizado en functions.php del tema */
/* lee button.js (->my-script) y localiza admin-ajax.php para my-script */
function add_my_script() {
wp_enqueue_script( 'my-script',
get_template_directory_uri() . '/js/button.js',
array ( 'jquery' ),
false,
true
);
wp_localize_script( 'my-script', 'my_ajax_object',
array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
}
add_action( 'wp_enqueue_scripts', 'add_my_script' );
