web-dev-qa-db-fra.com

Confus sur AJAX soumettre le formulaire à travers un modèle de page

Je pense que j'ai trop consulté de code et que je me suis confus en essayant de mieux comprendre les formulaires dans WordPress avec AJAX. Je suis parti cette semaine pour apprendre à créer un formulaire pour une page et à le soumettre via AJAX.

La page est un modèle et l’action que j’ai étudiée concerne deux solutions de traitement. Une via une redirection vers un PHP, tel que:

<form action="<?php echo get_template_directory_uri() . "/validation.php"; ?>" id="contactForm">
</form>

après avoir lu plusieurs articles sur le sujet qu’une validation séparée du formulaire devrait être faite. Est-ce correct et pourquoi? Ensuite, l’autre problème est que si je souhaite traiter le formulaire sur la page de modèle, l’action de formulaire doit ressembler à ceci:

<form action="#" id="contactForm">
</form>

mais en dehors de WordPress, j'ai déjà vu:

<form action="" id="contactForm">
</form>

pourquoi est-ce? Sur la partie AJAX, j'ai constaté une différence de:

jQuery.ajax({
    type :"post",
    url: ajaxurl,
    }
});

puis une autre URL de:

jQuery.ajax({
    type :"post",
    dataType:"json",
    url: MBAjax.admin_url,
    }
});

et enfin:

jQuery.ajax({
    type :"post",
    dataType:"json",
    url: /wp-admin/admin-ajax.php?action=contactForm",
    }
});

Alors, quelle est la bonne façon d’écrire l’action dans WordPress si:

  • Si le formulaire est traité sur la même page?
  • Si un fichier PHP séparé valide le formulaire?

Alors, quel est le bon appel AJAX dans WordPress?

Points de référence:


Modifier:

Après une lecture plus approfondie, a décidé de passer aux soumissions RESTful. J'ai référencé " REST API pour Absolute Beginners " mais je n'obtiens pas le retour que j'espère:

HTML:

<form id="contactForm" action="" method="POST">
    <div class="form-group">
        <label for="form_email"><span class="asterisk">*</span>Email address:</label>
        <input type="email" class="form-control" id="form_email">
    </div>
    <div class="form-group">
        <button id="form_submit" class="supportbutton" type="submit">Submit</button>
    </div>
</form>
<div id="testForm"></div>

jQuery:

$(document).ready(function() {
    $('#contactForm').submit(function(e) {
        e.preventDefault(); 
        jQuery.ajax({
            url: '<?php echo home_url(); ?>/wp-json/darthvader/v1/contact',
            type: 'post',
            dataType: 'json',
            data: $('#contactForm').serialize(),
            success: function(data) {
                $("#testForm").html(data);
            },
             error: function() {
                alert("There was an issue");
             },
        });
    });
});

functions.php:

add_action('rest_api_init', function() {
    register_rest_route('darthvader/v1', '/contact/', array(
        'methods'   => 'POST',
        'callback'  => 'darth_contact_form'
    ));
});
function darth_contact_form(\WP_REST_Request $request) {
    $email = $request['form_email'];
    return "Your contact request had the title " . $email;
}

Pourquoi ne reçois-je que Your contact request had the title sur le retour et pas le courrier électronique?

1
<form action="<?php echo get_template_directory_uri() . "/validation.php"; ?>" id="contactForm">

????

Donc, je vais exposer les principes de base, de sorte que vous avez un cadre pour aller de l'avant avec

Fixation Admin AJAX

Je vais donc en parler très brièvement car ce n’est pas le noeud de ma réponse, mais serait utile:

  • Ajouter un champ de saisie masqué nommé action plutôt que de l'ajouter à l'URL
  • validation.php et tous les autres fichiers autonomes doivent brûler avec le feu de mille soleils, effectuez cette validation dans JS, puis à nouveau dans le gestionnaire de formulaire. Le traitement et la validation du formulaire sont la même étape, sinon quelqu'un pourrait ignorer la validation et passer directement au traitement

Enfin, utilisez un gestionnaire de formulaire standard lorsque JS n'est pas utilisé/possible, vérifiez l'existence d'un élément du formulaire qui ne se produirait que s'il a été soumis, puis soumettez le formulaire à la même page en disposant d'un attribut d'action vide. par exemple:

if ( !empty( $_POST['form_page'] ) ) {
    $valid = false;

    // do validation
    // 
    if ( true === $valid ) {
        // yay do whatever submitting the form is meant to do
        // if it's a multipage form, handle that here
    } else {
        get_template_part( 'form' ); // show the form again, but with warnings for validation
    }
} else {
    get_template_part( 'form' );
}

Soumission de formulaire RESTful

Changez votre soumission de formulaire jQuery pour utiliser un point de terminaison REST, appelons ce darthvader/v1/contact, j'ai utilisé du code provenant d'une réponse stackoverflow ici :

jQuery('input#submitButton').click( function() {
    jQuery.ajax({
        url: '/wp-json/darthvader/v1/contact',
        type: 'post',
        dataType: 'json',
        data: jQuery('form#contactForm').serialize(),
        success: function(data) {
            //... do something with the data...
        }
    });
});

C'est à peu près toutes les soumissions de formulaire via l'API REST dont vous aurez jamais besoin, mais vous avez toujours besoin de ce noeud final, '/ wp-json/darthvader/v1/form' doit être créé, aussi allons-nous dire WP nous voulons un terminal qui accepte les POST:

add_action( 'rest_api_init', function () {
        register_rest_route( 'darthvader/v1', '/contact/', array(
                'methods' => 'POST',
                'callback' => 'darth_contact_form'
        ) );
} );

Ensuite, définissez ce qui se passera quand cela s'appelle:

function darth_contact_form( \WP_REST_Request $request ) {
    //
}

C’est là que nous traiterons notre formulaire, par exemple:

function darth_contact_form( \WP_REST_Request $request ) {
    $title = $request['title'];
    $message = $request['message'];
    // send an email or create a post, or whatever
    // the contact form does when its submitted
    return "Your contact request had the title ".$title;
}

La valeur de retour est convertie en JSON et renvoyée au navigateur afin que vous puissiez la gérer dans la fonction de réussite en javascript que vous avez vue précédemment dans cette réponse. Vous pouvez également renvoyer d'autres réponses, par exemple:

return \WP_REST_Response( "Bad request, X Y and Z are empty", 400);

et vous pouvez retourner un objet WP_Error pour indiquer que quelque chose ne va pas ou est incorrect:

return new WP_Error( 'awesome_no_author', 'Invalid author', array( 'status' => 404 ) );

Vous pouvez effectuer votre validation à l'intérieur du noeud final, mais vous pouvez également le faire pour vous en spécifiant les champs à attendre et une fonction pour les valider, mais je laisse cela comme un exercice (ou une nouvelle question) pour vous.

3
Tom J Nowell

Chaque processus AJAX comporte 4 étapes fondamentales:

  1. Envoyer une demande au serveur de manière asynchrone
  2. Traiter les tâches côté serveur
  3. Récupérer la réponse du serveur
  4. Apporter des modifications côté client en fonction de la réponse du serveur

Créer une requête sur le serveur

Il y a beaucoup de manières et méthodes pour faire ceci. Cela peut être fait à la fois par jQuery et JavaScript. Cependant, depuis que jQuery a facilité les choses, je vais l'utiliser. jQuery offre 3 fonctions différentes avec des fonctionnalités similaires. Ces fonctions sont:

  • $.ajax(); - Prend en charge les méthodes POST et GET
  • $.get(); - Méthode simple GET
  • $.post(); - Méthode simple POST

Puisque je ne suis pas sûr de la méthode que vous allez utiliser, je vais procéder à $.ajax();. Je publierai un exemple de code sur le serveur, puis afficherai un message en fonction de la réponse du serveur. Déclarons une fonction jQuery qui gère notre soumission.

Cette fonction enverra un nom d'utilisateur au serveur.

function sendMyForm( string ) {
    // Begin an Ajax request
    $.ajax({
        type: 'POST',                   // Submission method
        url: url_object.url_string + '/wp-json/darthvader/ajax_submission', // I will explain this later
        data: { username : string },        // Data to be sent to server
        dataType: 'json',               // You should set this to JSON if you are going to use the REST api
        beforeSend: function(){         // Let's show a message while the request is being processed
            $('#status').html('<span>Processing</span>');
        },
        success: function ( response ) {
            // The Ajax request is successful. This doesn't mean the
            // sever was able to do the task, it just means that the
            // server did send a response. So, let's check the response
            if( response.success == true ) {
                $('#status').html('<span>Success</span>');
                $('#message').html('<span>' + response.message + '</span>');
            } else {
                $('#status').html('<span>Failed</span>');
                $('#message').html('<span>' + response.message + '</span>');
            }
        },
        error: function(){              // The request wasn't successful for some reason
            $('#status').html('<span>Unknown error.</span>');
        }
    });
};

Bon, il faut maintenant lier une action à notre bouton. Il y a plusieurs façons de le faire aussi. Par exemple, empêchez la soumission de formulaires, la sérialisation de données, etc. Je ne vais même pas créer un formulaire.

Je vais créer une div HTML personnalisée pour démontrer que nous n'avons même pas besoin d'un formulaire. Voici notre code HTML qui ressemble à un formulaire:

<div>
    <p id="status"></p>
    <p id="message"></p>
    <input id="my-input" type="text"/>
    <span id="button">This is our button!</span>
</div>

Maintenant, lions une action Clink à notre bouton, qui n’est en réalité pas un bouton! Vous a trompé.

$('#button').on('click',function(){
    // Get the value of our input box
    var username = $('#my-input').val();
    // Call our Ajax function and pass the username to it
    sendMyForm( string );
});

Bon, maintenant le formulaire sera soumis au clic de l'utilisateur.

Création d'un itinéraire pour traiter la demande

Depuis que j'ai déclaré le type de données au format JSON, je vais utiliser l'API REST qui génère notre contenu au format JSON par défaut.

Vous pouvez utiliser tout ce que vous souhaitez, tel qu'admin Ajax, dans la mesure où il s'agit d'une bonne pratique et qui n'a pas d'incidence sur les performances ni de problème de sécurité.

Enregistrons une route REST pour le moment.

add_action( 'rest_api_init','my_rest_route' ); 
function my_rest_route() {
    register_rest_route( 
        'darthvader',   // Base path here
        '/ajax_submission/',    // Child path
        array(
            'methods' => 'POST',
            'callback' => 'darth_contact_form'
        ) 
    );
}

Maintenant il est temps de s'amuser. Gérons les données reçues, allons-nous?

function darth_contact_form( \WP_REST_Request $request ){
    // Get the data that was sent to server
    $data = $request['username'];
    // Check if it's empty and send the response
    if( !empty( $data ) ){
        // Remember these from our Ajax call? This is where we set them
        $response['status'] =  true;
        $response['message'] =  'You have entered a username!';
    } else{
        $response['status'] =  false;
        $response['message'] =  'Why didn\'t you enter a username?';
    }
    // Don't forget to return the data
    return $response;
}

Une touche finale

Rappelez-vous cette ligne?

url: url_object.url_string

C’est le chemin qui mène à notre route REST. Comme le domaine peut changer, il est sage de le former de manière dynamique en utilisant wp_localize_script. Pour ce faire, nous sauvegardons tous nos scripts dans un fichier nommé script.js, puis nous le mettons en file d'attente et le localisons.

wp_enqueue_script( 'my-script', get_template_directory_uri().'/js/script.js', array( 'jquery' ), '', true );

$localized = array(
    'url_string' => site_url(), // This is where that url_string came from
);
wp_localize_script( 'my-script', 'url_object', $localized );

Nous pouvons maintenant accéder à la site_url(); en utilisant url_object.url_string dans notre script!

C'est tout pour le moment. Cliquez sur le bouton et amusez-vous.

2
Jack Johansson