Mengirimkan Formulir Tanpa Memuat Ulang Halaman: Implementasi AJAX Di WordPress

Diterbitkan: 2022-03-10
Ringkasan cepat Ada banyak solusi “tanpa penyegaran halaman” di luar sana, tetapi ini adalah solusi yang dapat Anda buat dengan AJAX. Dalam tutorial ini, Anda dapat mempelajari cara membuat plugin sederhana yang memungkinkan pembaca mengirim laporan tanpa memuat ulang halaman.

Jika Anda pernah ingin mengirim formulir tanpa memuat ulang halaman, berikan fungsi pencarian lihat ke depan yang meminta pengguna dengan saran saat mereka mengetik, atau simpan otomatis dokumen, maka yang Anda butuhkan adalah AJAX (juga dikenal sebagai XHR ). Permintaan di balik layar dikirim ke server, dan mengembalikan data ke formulir Anda. Setiap kali Anda melihat animasi pemuat setelah Anda melakukan beberapa tindakan pada halaman, itu mungkin permintaan AJAX yang dikirimkan ke server.

Dalam artikel ini, saya akan memandu Anda melalui seluruh proses pembuatan dan penanganan panggilan AJAX. Anda akan belajar tidak hanya cara melakukan panggilan AJAX, tetapi juga cara melakukannya dengan cara terbaik menggunakan fitur yang ditawarkan WordPress langsung kepada pengembang. Kami akan membuat plugin sederhana yang memungkinkan pembaca mengirim laporan ke administrator dengan informasi tentang bug apa pun yang mungkin mereka temukan di situs web Anda.

Proses pengiriman laporan bug
Seorang pengguna menemukan bug dan mengklik tombol "Laporkan Bug". Akibatnya, formulir untuk pesan disajikan. Mengklik tombol untuk kedua kalinya akan mengirim pengguna ke administrator.

Di akhir artikel, Anda dapat mengunduh contoh kerja dan memeriksa kode secara penuh.

Mari kita menggali!

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

AJAX

"Tanpa memuat ulang halaman" adalah kalimat kunci di sini. AJAX adalah singkatan dari Asynchronous JavaScript And XML karena pada awalnya, data yang dikembalikan dari server seharusnya dalam XML. Namun, lebih mudah mengirimnya dalam JSON, yang lebih disukai JavaScript.

Kami akan menggunakan AJAX untuk mengirim email. Anda tidak dapat melakukannya dari front-end, jadi Anda harus memanggil back-end. Biasanya, kami akan mengirim permintaan POST ke server, menanganinya dan mengarahkan pengguna kembali ke halaman dengan formulir. Dalam iterasi ini, kami tidak ingin memuat ulang halaman. Sebagai gantinya, kami memanggil backend secara langsung di mana kami akan mengambil data formulir dengan JavaScript, lalu mengirim permintaan asinkron ke server untuk menangani respons.

Ada tiga hal yang dibutuhkan WordPress AJAX — lima di antaranya agar berfungsi dengan baik . Ini adalah:

  • Objek untuk aksi AJAX
  • skrip JavaScript
  • tindakan WordPress
  • Perlindungan
  • Penanganan kesalahan

Mari kita lihat lebih dekat satu per satu.

Obyek

Objek kita adalah bentuknya. Ini adalah hal yang kami tangani dengan JavaScript. Saya mulai dengan membuat file dengan header yang dibutuhkan oleh plugin WordPress dan meletakkan objek kosong di dalamnya. Pada akhirnya, saya membuat instance baru dari kelas plugin.

 <?php /* Plugin Name: Report a bug Description: Allow your visitors to report a bug in your articles Author: Jakub Mikita Author URI: https://underdev.it Version: 1.0 License: GPL2 Text Domain: reportabug */ class Report_a_bug { } new Report_a_bug();

Meskipun saya menggunakan beberapa OOP di sini, kami tidak akan menggunakan praktik lanjutan apa pun. Kode akan bekerja dengan baik ketika ditulis secara prosedural dengan fungsi terpisah. Tetapi objek dalam plugin WordPress memiliki satu keuntungan: Anda tidak perlu mengawali fungsi Anda — hanya nama kelas yang harus unik.

Mari kita tampilkan formulir kita kepada pengguna. Kami akan menghubungkan ke filter the_content dan menyematkan formulir di akhir setiap posting. Di konstruktor kelas saya menambahkan filter:

 public function __construct() { add_filter( 'the_content', array( $this, 'report_button' ), 10, 1 ); }

Dan membuat metode panggilan balik dengan formulir HTML:

 public function report_button( $content ) { // display button only on posts if ( ! is_single() ) { return $content; } $content .= '<div class="report-a-bug"> <button class="show-form" data-post_>' . __( 'Report a bug', 'reportabug' ) . '</button> <textarea class="report-a-bug-message" placeholder="' . __( 'Describe what\'s wrong...', 'reportabug' ) . '"></textarea> <p class="report-a-bug-response"></p> </div>'; return $content; }

Formulir memiliki semua markup yang diperlukan:

  • Tombol untuk menampilkan formulir dan mengirim pesan;
  • textarea ;
  • Wadah untuk respons (kita akan menggunakan ini nanti).

Button memiliki atribut data-post_id yang menyimpan ID posting saat ini. Kami akan mengambil ini di JavaScript untuk mengidentifikasi artikel.

Kita hanya memerlukan beberapa gaya dasar, jadi mari daftarkan stylesheet kita sendiri dengan tindakan wp_enqueue_scripts dan panggilan balik yang sesuai:

 public function __construct() { add_filter( 'the_content', array( $this, 'report_button' ), 10, 1 ); add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) ); } function scripts() { wp_enqueue_style( 'report-a-bug', plugin_dir_url( __FILE__ ) . 'css/style.css' ); }

Stylesheet itu sendiri sangat sederhana. Kami ingin merapikan desain.

 .report-a-bug-message { display: none; margin-top: 1em; } .report-a-bug-response { margin-top: 1em; }

Beginilah tampilan tombolnya:

Laporkan tombol bug
Tombol 'Laporkan bug'

Naskah

Kami memiliki objek kami siap untuk menempatkan beberapa kehidupan di dalamnya. Alih-alih melakukannya dalam JavaScript biasa, kita akan menggunakan jQuery yang dimuat WordPress secara default di setiap halaman.

Dalam metode skrip yang ada, saya akan menambahkan file JS menggunakan fungsi wp_enqueue_script .

 function scripts() { wp_enqueue_style( 'report-a-bug', plugin_dir_url( __FILE__ ) . 'css/style.css' ); wp_enqueue_script( 'report-a-bug', plugin_dir_url( __FILE__ ) . 'js/scripts.js', array( 'jquery' ), null, true ); // set variables for script wp_localize_script( 'report-a-bug', 'settings', array( 'send_label' => __( 'Send report', 'reportabug' ) ) ); }

Saya juga menggunakan fungsi wp_localize_script untuk meneruskan label tombol yang diterjemahkan ke JS. Kami tidak memiliki fungsi gettext dalam JavaScript, jadi kami harus melakukannya di sini. Fungsi ini akan membuat objek pengaturan yang dapat diakses langsung dari skrip kita.

Dalam skrip kami, kami akan mendengarkan klik tombol. Setelah itu terjadi, kami akan menampilkan area textarea dan mengganti kelas tombol untuk mendengarkan klik kedua yang mengirimkan formulir.

 ( function( $ ) { $( document ).ready( function() { $( '.report-a-bug' ).on( 'click', '.show-form', function( event ) { // change label and switch class $( this ).text( settings.send_label ).removeClass( 'show-form' ).addClass( 'send-report' ); // show textarea $( '.report-a-bug-message' ).slideDown( 'slow' ); }) }); })( jQuery );

Berikut progres saat ini:

Drop-down textarea saat diklik
tarik-turun textarea saat diklik

Ini adalah waktu terbaik untuk membuat permintaan AJAX!

Permintaan AJAX ke WordPress

Untuk mengirim permintaan AJAX, Anda benar-benar hanya membutuhkan satu-dan-satunya parameter: URL yang diminta. WordPress memiliki file khusus untuk AJAX, jadi kita tidak perlu membuatnya sendiri. Ini /wp-admin/admin-ajax.php .

Selama kita berada di area wp-admin , URL file ini tersedia di JS di variabel ajaxurl . Di front-end, kita harus melewati variabel ini sendiri. Untungnya kita sudah menggunakan fungsi wp_localize_script , jadi kita bisa menambahkan kunci lain ke dalamnya:

 wp_localize_script( 'report-a-bug', 'settings', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'send_label' => __( 'Send report', 'reportabug' ) ) );

Kami telah menyiapkan semua variabel jadi mari kita buat panggilan AJAX. Kami akan mengirimkannya setelah pengguna mengklik tombol untuk kedua kalinya.

 $( '.report-a-bug' ).on( 'click', '.send-report', function( event ) { var $button = $( this ); $button.width( $button.width() ).text('...'); // set ajax data var data = { 'action' : 'send_bug_report', 'post_id': $button.data( 'post_id' ), 'report' : $( '.report-a-bug-message' ).val() }; $.post( settings.ajaxurl, data, function( response ) { console.log( 'ok' ); } ); } );

Kami mendengarkan klik di kelas yang kami aktifkan tombol sebelumnya.

Seperti yang Anda lihat, saya mengubah teks tombol menjadi “…” Mengapa? Karena itu praktik yang baik untuk menunjukkan kepada pengguna bahwa sesuatu sedang terjadi. Permintaan AJAX bergantung pada kinerja server dan akan memakan waktu. Mungkin 30ms, tapi mungkin juga 3 detik. Jika setelah mengklik tombol sepertinya tidak ada efek, kemungkinan besar tombol akan diklik untuk kedua kalinya. Ini akan menduplikasi permintaan karena seperti yang Anda ketahui sekarang, ini tidak sinkron.

Selanjutnya, saya membuat objek data . Ini berisi semua variabel yang akan dikirim ke panggilan balik server. File admin-ajax.php WordPress membutuhkan properti action. Ini harus unik kecuali Anda ingin plugin lain menangani permintaan Anda. Sisa parameter adalah opsional. Saya mengirim ID pos dan pesan laporan dari textarea .

Kami kemudian memanggil metode $.post . Selanjutnya, Anda dapat menebaknya; itu mengirim permintaan POST. Ini adalah metode singkatan, tetapi Anda juga dapat menggunakan metode $.ajax , yang memiliki lebih banyak opsi. Sebagai parameter pertama kita harus melewati URL file handler kita, kemudian parameter dan kemudian fungsi callback sukses. Ini adalah tempat di mana kita menangani respon. Untuk saat ini, kami hanya mengirim pesan sederhana ke konsol browser.

Mengirim permintaan AJAX ke back-end
Mengirim permintaan AJAX ke back-end

Kami siap menangani permintaan di back-end.

Tindakan WordPress

Anda mungkin bertanya-tanya bagaimana kita menghubungkan ke admin-ajax.php . Dengan tindakan, tentu saja! WordPress memiliki dua jenis tindakan:

 wp_ajax_nopriv_{$action} wp_ajax_{$action}

Di mana $action berada, nama tindakan diteruskan dalam params AJAX. Ini send_bug_report dalam kasus kami.

Tindakan pertama ini akan dijalankan hanya untuk pengguna yang tidak masuk. Yang kedua hanya untuk pengguna yang masuk. Jadi jika Anda ingin permintaan ditangani untuk keduanya, Anda harus mendefinisikan keduanya. Inilah yang saya lakukan di konstruktor kelas:

 public function __construct() { add_filter( 'the_content', array( $this, 'report_button' ), 10, 1 ); add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) ); add_action( 'wp_ajax_nopriv_send_bug_report', array( $this, 'send_bug_report' ) ); add_action( 'wp_ajax_send_bug_report', array( $this, 'send_bug_report' ) ); }

Dalam panggilan balik, saya baru saja mendapatkan judul posting, dan saya mengirim email:

 function send_bug_report() { $data = $_POST; $post_title = get_the_title( intval( $data['post_id'] ) ); wp_mail( '[email protected]', 'Bug report in post: ' . $post_title, $data['report'] ); wp_send_json_success( __( 'Thanks for reporting!', 'reportabug' ) ); }

Bagian terpenting dalam menangani AJAX di WordPress adalah fungsi terakhir - wp_send_json_success yang mencetak output yang dikodekan JSON dan mati. Yang kita butuhkan untuk mendapatkan respons dengan panggilan balik sukses AJAX. Ia juga memiliki saudara kembar, wp_send_json_error , tetapi kita akan membahas bagian itu nanti.

Objek dari fungsi ini memiliki dua properti:

  • kesuksesan
    Adalah boolean dan tergantung apakah Anda menyebutnya fungsi sukses atau kesalahan.
  • data
    Jika Anda memberikan parameter untuk fungsi.

Itu semua dari sisi back-end. Mari kita tangani responsnya di JS.

Kami akan menghapus tombol dan textarea dan menampilkan pesan yang dikembalikan dari server dalam wadah yang kami siapkan sebelumnya:

 $.post(settings.ajaxurl, data, function(response) { // remove button and textarea $button.remove(); $('.report-a-bug-message').remove(); // display success message $('.report-a-bug-response').html( response.data ); });

Dan itu saja! Kami memiliki panggilan AJAX yang berfungsi! Tapi jangan berhenti di situ. Permintaan kami tidak aman dan tentu saja tidak ramah pengguna. Kita harus memastikan permintaan dijalankan hanya ketika harus.

Perlindungan

nonce

Nonce adalah "nomor yang digunakan sekali." Ini adalah hash pendek yang dibuat dari string input. Kami dapat menggunakannya untuk memvalidasi permintaan — jika itu benar-benar dibuat oleh WordPress dan tidak ada yang memalsukannya.

Kami akan menggunakan atribut data lain untuk tombol:

 $nonce = wp_create_nonce( 'report_a_bug_' . get_the_ID() ); $content .= '<div class="report-a-bug"> <button class="show-form" data-nonce="' . $nonce . '" data-post_>' . __( 'Report a bug', 'reportabug' ) . '</button> <textarea class="report-a-bug-message" placeholder="' . __( 'Describe what\'s wrong...', 'reportabug' ) . '"></textarea> <p class="report-a-bug-response"></p> </div>';

Seperti yang Anda lihat, saya menambahkan ID posting ke string input. Kami akan menyediakan ID ini di properti permintaan AJAX, jadi ini lebih aman.

Sekarang kita harus menambahkan nonce ke properti AJAX:

 // set ajax data var data = { 'action' : 'send_bug_report', 'post_id': $button.data('post_id'), 'nonce' : $button.data('nonce'), 'report' : $('.report-a-bug-message').val() };

Sekarang kita akan memvalidasinya di backend menggunakan fungsi check_ajax_referer , yang disediakan WordPress:

 function send_bug_report() { $data = $_POST; // check the nonce if ( check_ajax_referer( 'report_a_bug_' . $data['post_id'], 'nonce', false ) == false ) { wp_send_json_error(); } $post_title = get_the_title( intval( $data['post_id'] ) ); wp_mail( '[email protected]', 'Bug report in post: ' . $post_title, sanitize_text_field( $data['report'] ) ); wp_send_json_success( __( 'Thanks for reporting!', 'reportabug' ) ); }

Untuk memvalidasi permintaan, kami harus membuat ulang string input, jadi saya menggunakan kunci post_id yang dikirim dari AJAX. Parameter kedua adalah kunci dalam $_REQUEST array . Ketiga mengontrol wp_die otomatis jika nonce tidak cocok.

Saya tidak ingin itu mati dengan sendirinya. Sebagai gantinya, saya menangkap hasil dari fungsi ini dan mengirim kesalahan JSON dalam objek yang bagus.

Anda mungkin juga memperhatikan penggunaan fungsi sanitize_text_field dalam parameter pesan email. Ini hanya untuk memastikan pengguna tidak akan mengirim skrip atau HTML berbahaya.

Terakhir, kita perlu membungkus panggilan balik sukses AJAX di JS dalam pernyataan if untuk memeriksa apakah permintaan berhasil:

 $.post(settings.ajaxurl, data, function(response) { if ( response.success == true ) { // remove button and textarea $button.remove(); $('.report-a-bug-message').remove(); // display success message $('.report-a-bug-response').html( response.data ); } });

Perlindungan Tombol

Anda tahu bahwa pengguna dapat mengklik tombol untuk kedua kalinya, sebelum AJAX menyelesaikan panggilan. Tapi ada satu trik sederhana yang akan memblokir klik kedua - menonaktifkan tombol. Jadi setelah klik, saya akan memblokirnya dan membuka blokirnya setelah mendapat respons:

 $('.report-a-bug').on('click', '.send-report', function(event) { var $button = $(this); $button.width( $button.width() ).text('...').prop('disabled', true); // set ajax data var data = {...}; $.post(settings.ajaxurl, data, function(response) { if ( response.success == true ) {...} // enable button $button.prop('disabled', false); }); });

Penanganan Kesalahan

Validasi

Bagaimana jika pengguna mencoba mengirim pesan kosong? Saya tidak ingin diganggu dengan email seperti itu. Mari kita blokir upaya ini dengan teknik validasi.

Di JS saya akan menambahkan validasi sederhana, untuk menunjukkan kepada pengguna bahwa ada yang tidak beres. Jika pesan kosong, pengguna akan melihat batas merah di sekitar area teks. Jika ada pesan di sana, kami memulihkan batas netral:

 $('.report-a-bug').on('click', '.send-report', function(event) { var $button = $(this); // check if message is not empty if ( $( '.report-a-bug-message' ).val().length === 0 ) { $( '.report-a-bug-message' ).css( 'border', '1px solid red' ); return false; } else { $( '.report-a-bug-message' ).css( 'border', '1px solid rgba(51, 51, 51, 0.1)' ); } // ... ajax });

Memeriksa Kesalahan Dalam Tindakan WordPress

Kami mungkin juga memiliki masalah dengan pengiriman email. Jika kita tidak mengecek hasil dari fungsi wp_mail , pengguna akan mendapatkan pesan sukses meskipun tidak ada email yang terkirim.

Mari kita tangani ini:

 function send_bug_report() { $data = $_POST; // check the nonce if ( check_ajax_referer( 'report_a_bug_' . $data['post_id'], 'nonce', false ) == false ) { wp_send_json_error(); } $post_title = get_the_title( intval( $data['post_id'] ) ); $result = wp_mail( '[email protected]', 'Bug report in post: ' . $post_title, sanitize_text_field( $data['report'] ) ); if ( $result == false ) { wp_send_json_success( __( 'Thanks for reporting!', 'reportabug' ) ); } else { wp_send_json_error(); } }

Seperti yang Anda lihat, kami telah menggunakan fungsi wp_send_json_error dua kali, tetapi tidak perlu menampilkan pesan unik untuk pengguna. Sebagai gantinya, dengan meneruskan deskripsi kesalahan yang tepat, saya akan menambahkan kunci lain ke objek pengaturan skrip kami yang akan mencakup kedua kesalahan:

 // set variables for script wp_localize_script( 'report-a-bug', 'settings', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'send_label' => __( 'Send report', 'reportabug' ), 'error' => __( 'Sorry, something went wrong. Please try again', 'reportabug' ) ) );

Yang tersisa untuk dilakukan adalah menampilkan kesalahan kepada pengguna:

 $.post( settings.ajaxurl, data, function( response ) { if ( response.success == true ) { // remove button and textarea $button.remove(); $( '.report-a-bug-message' ).remove(); // display success message $( '.report-a-bug-response' ).html( response.data ); } else { // display error message $( '.report-a-bug-response' ).html( settings.error ); } // enable button and revert label $button.text( settings.send_label ).prop( 'disabled', false ); } );

Contoh Lengkap

Kami telah melakukannya! Permintaan AJAX kami telah dibuat; itu aman dan ramah pengguna. Inilah yang akan dilihat pengguna jika terjadi kesalahan:

Contoh selesai, permintaan AJAX dengan validasi
Contoh selesai, permintaan AJAX dengan validasi

Di bawah ini Anda dapat mengunduh plugin lengkap dan memeriksa panduan pengguna:

  • Unduh plugin di Github
  • Unduh plugin di Wordpress.org
  • Buka panduan pengguna

Saya harap ini memberi Anda dasar yang bagus untuk solusi "tanpa penyegaran halaman" Anda sendiri. Anda dapat melakukan ini untuk semua formulir di situs web Anda. Ini juga merupakan cara yang bagus untuk mengoptimalkan bagian berat apa pun dari situs web yang tidak harus segera dimuat, seperti daftar besar produk dalam drop-down. Anda dapat memuatnya melalui AJAX setelah mengklik drop-down — sesederhana itu .

Kemungkinannya hampir tidak terbatas. Beri tahu saya di komentar apa ide Anda!