Trong bài đăng này, tôi sẽ chia sẻ một cách đơn giản để sử dụng tìm kiếm bộ lọc Ajax cho WordPress. Tôi thích sử dụng Ajax trong các dự án của mình. Nó là gọn gàng, nhẹ và nhanh chóng. Quan trọng nhất là trải nghiệm người dùng tốt hơn nhiều.

Trong demo này hướng dẫn ae viết form lọc danh sách các bộ film, kết quả tìm kiếm theo: Tên / Năm / Xếp hạng / Ngôn ngữ / Giới tính => A/e bắt đầu thôi 🙂
Ajax Filter trong demo này hoạt động như thế nào?
Ajax rất đơn giản chịu khó luyện tập, đưa ra tình huống và thực hiện nó. Demo lần này lọc theo (từ khóa tìm kiếm, năm, xếp hạng, ngôn ngữ, thể loại) đến máy chủ và nó sẽ thực hiện một truy vấn với dữ liệu sau đó trả về kết quả.

Thiết lập Post Type Movies
Copy đoạn bên dưới add vào file function.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php function register_custom_post_type_movie() { $args = array( "label" => __( "Movies", "" ), "labels" => array( "name" => __( "Movies", "" ), "singular_name" => __( "Movie", "" ), "featured_image" => __( "Movie Poster", "" ), "set_featured_image" => __( "Set Movie Poster", "" ), "remove_featured_image" => __( "Remove Movie Poster", "" ), "use_featured_image" => __( "Use Movie Poster", "" ), ), "public" => true, "publicly_queryable" => true, "show_ui" => true, "show_in_rest" => false, "has_archive" => false, "show_in_menu" => true, "exclude_from_search" => false, "capability_type" => "post", "map_meta_cap" => true, "hierarchical" => false, "rewrite" => array( "slug" => "movie", "with_front" => true ), "query_var" => true, "supports" => array( "title", "editor", "thumbnail" ), "taxonomies" => array( "category" ), ); register_post_type( "movie", $args ); } add_action( 'init', 'register_custom_post_type_movie' ); |
Giờ ít ai ngồi gõ từng dòng code dùng cái có sẵn cho nó nhanh thực tế nó trả khác gì nhau. Dưới đây là các công cụ mà bạn có thể xem qua.
- Custom Post Type Generator – Cho phép bạn tạo custom post type nhanh chóng bằng việc chọn một số tùy chọn có sẵn và lấy toàn bộ code về. Bạn chỉ cần copy đoạn code này vào file functions.php hoặc làm plugin riêng là xong.
- Custom Post Type UI – Plugin miễn phí cho phép tạo custom post type nhanh chóng trực tiếp trong WP-Admin.
Vậy thôi, còn các công cụ khác nó nhiều tính năng quá nên mình không đề cập tới vì rất hại não.
=> Trước khi tạo một số bài đăng về phim, chúng ta cần tạo các trường tùy chỉnh được sử dụng làm bộ lọc. Để tạo các trường cho Custom Post Type mình hay dùng Advanced Custom Field ae nào thích dùng Metabox tạo trường thì dùng tùy thuộc vào code..

Sau khi tạo xong các trường cho Movies => bắt đầu nhập liệu thôi

Tạo Shortcode cho Ajax Filter Search
Đoạn này, tạo một shortcode hiển thị Form Search dễ dàng nhét bất kì chỗ nào trên trang web bạn thích. Đặt đoạn mã sau vào tệp functions.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php // Shortcode: [my_ajax_filter_search] function my_ajax_filter_search_shortcode() { ob_start(); ?> Test Shortcode Output <!-- FORM CODE WILL GOES HERE --> <?php return ob_get_clean(); } add_shortcode ('my_ajax_filter_search', 'my_ajax_filter_search_shortcode'); |
Trên là đoạn khởi tạo shortcode [my_ajax_filter_search] để biết nó có chạy ko add thử nó vào trang bất kì kiểm tra xem nó có hoạt động không. Oke tiếp tục add thêm các trường của form vào…..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
<?php // Shortcode: [my_ajax_filter_search] function my_ajax_filter_search_shortcode() { ob_start(); ?> <div id="my-ajax-filter-search"> <form action="" method="get"> <input type="text" name="search" id="search" value="" placeholder="Search Here.."> <div class="column-wrap"> <div class="column"> <label for="year">Year</label> <input type="number" name="year" id="year"> </div> <div class="column"> <label for="rating">IMDB Rating</label> <select name="rating" id="rating"> <option value="">Any Rating</option> <option value="9">At least 9</option> <option value="8">At least 8</option> <option value="7">At least 7</option> <option value="6">At least 6</option> <option value="5">At least 5</option> <option value="4">At least 4</option> <option value="3">At least 3</option> <option value="2">At least 2</option> <option value="1">At least 1</option> </select> </div> </div> <div class="column-wrap"> <div class="column"> <label for="language">Language</label> <select name="language" id="language"> <option value="">Any Language</option> <option value="english">English</option> <option value="korean">Korean</option> <option value="hindi">Hindi</option> <option value="serbian">Serbian</option> <option value="malayalam">Malayalam</option> </select> </div> <div class="column"> <label for="genre">Genre</label> <select name="genre" id="genre"> <option value="">Any Genre</option> <option value="action">Action</option> <option value="comedy">Comedy</option> <option value="drama">Drama</option> <option value="horror">Horror</option> <option value="romance">Romance</option> </select> </div> </div> <input type="submit" id="submit" name="submit" value="Search"> </form> <ul id="ajax_filter_search_results"></ul> </div> <?php return ob_get_clean(); } add_shortcode ('my_ajax_filter_search', 'my_ajax_filter_search_shortcode'); |
Bắt đầu đến đoạn ae cần tập chung, nhầm 1 tẹo là ko chạy được đâu :))
Thêm tập lệnh cần thiết
Tạo tệp script.js mới trong thư mục chủ đề của chúng tôi để thêm các mã javascript của chúng tôi. Thêm mã sau vào trước hàm shortcode mà chúng ta đã thêm trước đó trên tệp functions.php .
1 2 3 4 5 6 7 |
<?php // Scripts for Ajax Filter Search function my_ajax_filter_search_scripts() { wp_enqueue_script( 'my_ajax_filter_search', get_stylesheet_directory_uri(). '/script.js', array(), '1.0', true ); wp_localize_script( 'my_ajax_filter_search', 'ajax_url', admin_url('admin-ajax.php') ); } |
Đoạn này sử dụng wp_localize_script () để dễ dàng sử dụng tệp admin-ajax.php .
Điều tiếp theo cần làm là gọi hàm my_ajax_filter_search_scripts () bên trong hàm my_ajax_filter_search_shortcode () .
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php // Shortcode: [my_ajax_filter_search] function my_ajax_filter_search_shortcode() { my_ajax_filter_search_scripts(); // Added here ob_start(); ?> <div id="my-ajax-filter-search"> <form action="" method="get"> .... .... |
Bằng cách này, các tập lệnh cần thiết cho bộ lọc / tìm kiếm ajax sẽ tải bất cứ khi nào chúng ta sử dụng shortcode.
Chuẩn bị dữ liệu để gửi yêu cầu
Thêm mã sau vào tệp script.js
1 2 3 4 5 6 7 8 9 10 11 12 |
$ = jQuery; var mafs = $("#my-ajax-filter-search"); var mafsForm = mafs.find("form"); mafsForm.submit(function(e){ e.preventDefault(); console.log("form submitted"); // we will add codes above this line later }); |
Ở đây đã thêm hai biến để dễ sử dụng và sau đó một hàm sẽ kích hoạt khi nhấn nút Search. Mã e.preventDefault (); phần ngăn tải lại trang. Bạn cũng sẽ thấy kết quả “form submitted” trên bảng điều khiển của trình duyệt.
Check oke thì xóa bỏ console.log(“form submitted”); thay bằng đoạn bên dưới.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
if(mafsForm.find("#search").val().length !== 0) { var search = mafsForm.find("#search").val(); } if(mafsForm.find("#year").val().length !== 0) { var year = mafsForm.find("#year").val(); } if(mafsForm.find("#rating").val().length !== 0) { var rating = mafsForm.find("#rating").val(); } if(mafsForm.find("#language").val().length !== 0) { var language = mafsForm.find("#language").val(); } if(mafsForm.find("#genre").val().length !== 0) { var genre = mafsForm.find("#genre").val(); } var data = { action : "my_ajax_filter_search", search : search, year : year, rating : rating, language : language, genre : genre } |
Lấy kết quả Ajax Filter
Copy dán đoạn trên vào file function.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
<?php // Ajax Callback add_action('wp_ajax_my_ajax_filter_search', 'my_ajax_filter_search_callback'); add_action('wp_ajax_nopriv_my_ajax_filter_search', 'my_ajax_filter_search_callback'); function my_ajax_filter_search_callback() { header("Content-Type: application/json"); $meta_query = array('relation' => 'AND'); if(isset($_GET['year'])) { $year = sanitize_text_field( $_GET['year'] ); $meta_query[] = array( 'key' => 'year', 'value' => $year, 'compare' => '=' ); } if(isset($_GET['rating'])) { $rating = sanitize_text_field( $_GET['rating'] ); $meta_query[] = array( 'key' => 'rating', 'value' => $rating, 'compare' => '>=' ); } if(isset($_GET['language'])) { $language = sanitize_text_field( $_GET['language'] ); $meta_query[] = array( 'key' => 'language', 'value' => $language, 'compare' => '=' ); } $tax_query = array(); if(isset($_GET['genre'])) { $genre = sanitize_text_field( $_GET['genre'] ); $tax_query[] = array( 'taxonomy' => 'category', 'field' => 'slug', 'terms' => $genre ); } $args = array( 'post_type' => 'movie', 'posts_per_page' => -1, 'meta_query' => $meta_query, 'tax_query' => $tax_query ); if(isset($_GET['search'])) { $search = sanitize_text_field( $_GET['search'] ); $search_query = new WP_Query( array( 'post_type' => 'movie', 'posts_per_page' => -1, 'meta_query' => $meta_query, 'tax_query' => $tax_query, 's' => $search ) ); } else { $search_query = new WP_Query( $args ); } if ( $search_query->have_posts() ) { $result = array(); while ( $search_query->have_posts() ) { $search_query->the_post(); $cats = strip_tags( get_the_category_list(", ") ); $result[] = array( "id" => get_the_ID(), "title" => get_the_title(), "content" => get_the_content(), "permalink" => get_permalink(), "year" => get_field('year'), "rating" => get_field('rating'), "director" => get_field('director'), "language" => get_field('language'), "genre" => $cats, "poster" => wp_get_attachment_url(get_post_thumbnail_id($post->ID),'full') ); } wp_reset_query(); echo json_encode($result); } else { // no posts found } wp_die(); } |
*Giải thích:
- Tại dòng 05 và 06, sử dụng add_action cho hàm my_ajax_filter_search_callback () . Nếu bạn đang sử dụng một tên hàm khác, bạn có thể thay đổi wp_ajax_my_ajax_filter_search thành wp_ajax_YOUR_FUNCTION_NAME . Điều tương tự cho wp_ajax_nopriv_my_ajax_filter_search
- Tại dòng 10, thêm header (“Content-Type: application / json”); để khai báo loại nội dung là json bởi vì, demo này sử dụng JSON để gửi kết quả trở lại trình duyệt.
- Ở dòng 12, thêm các meta_query dựa trên các trường bộ lọc. Trả về kết quả theo bộ lọc mà bạn nhập hoặc select
- Ở dòng 41, thêm các quy tắc tax_query vì trường hợp này sử dụng các danh mục WordPress làm Thể loại phim.
- Cuối cùng, ở dòng 52, ‘s’ => $ search trả lại kết quả tên phim muốn tìm kiếm
- Sau truy vấn, tại dòng 95, chúng tôi lặp lại kết quả được mã hóa dưới dạng JSON mà chúng tôi sẽ sử dụng trong bước tiếp theo trong hàm jQuery Ajax.
Hàm jQuery Ajax
Bây giờ chúng ta sẽ sử dụng hàm jQuery Ajax để hoàn thành bước cuối cùng . Thêm mã sau vào tệp script.js .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
$ = jQuery; var mafs = $("#my-ajax-filter-search"); var mafsForm = mafs.find("form"); mafsForm.submit(function(e){ e.preventDefault(); if(mafsForm.find("#search").val().length !== 0) { var search = mafsForm.find("#search").val(); } if(mafsForm.find("#year").val().length !== 0) { var year = mafsForm.find("#year").val(); } if(mafsForm.find("#rating").val().length !== 0) { var rating = mafsForm.find("#rating").val(); } if(mafsForm.find("#language").val().length !== 0) { var language = mafsForm.find("#language").val(); } if(mafsForm.find("#genre").val().length !== 0) { var genre = mafsForm.find("#genre").val(); } var data = { action : "my_ajax_filter_search", search : search, year : year, rating : rating, language : language, genre : genre } $.ajax({ url : ajax_url, data : data, success : function(response) { mafs.find("ul").empty(); if(response) { for(var i = 0 ; i < response.length ; i++) { var html = "<li id='movie-" + response[i].id + "'>"; html += " <a href='" + response[i].permalink + "' title='" + response[i].title + "'>"; html += " <img src='" + response[i].poster + "' alt='" + response[i].title + "' />"; html += " <div class='movie-info'>"; html += " <h4>" + response[i].title + "</h4>"; html += " <p>Year: " + response[i].year + "</p>"; html += " <p>Rating: " + response[i].rating + "</p>"; html += " <p>Language: " + response[i].language + "</p>"; html += " <p>Director: " + response[i].director + "</p>"; html += " <p>Genre: " + response[i].genre + "</p>"; html += " </div>"; html += " </a>"; html += "</li>"; mafs.find("ul").append(html); } } else { var html = "<li class='no-result'>No matching movies found. Try a different filter or search keyword</li>"; mafs.find("ul").append(html); } } }); // we will add codes above this line later }); |
=> thế là chạy thôi còn không chạy thì ae xem lại, đoạn mã này đã check chạy ầm ầm
Đoạn style form này ae ném vào file style.css nhé !
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
.column-wrap { display: flex; justify-content: space-between; flex-wrap: wrap; margin: 20px 0 } .column-wrap .column { width: 49%; } .column-wrap .column:last-child { float: right; } #my-ajax-filter-search label { display: block; font-weight: bold; font-style: italic; } #my-ajax-filter-search select { width: 100%; background-color: #f7f7f7; padding: 0.625em 0.4375em; border: 1px solid #d1d1d1; } #ajax_filter_search_results { list-style: none; display: flex; justify-content: start; flex-wrap: wrap; margin-top: 30px; } #ajax_filter_search_results li { width: 23.5%; float: left; margin-right: 2%; overflow: hidden; position: relative; margin-bottom: 20px; } #ajax_filter_search_results li.no-result { width: 100%; text-align: center; } #ajax_filter_search_results li:nth-child(4n+4) { margin-right: 0; } .movie-info h4 { margin-bottom: 10px; color: #fff; } .movie-info p { margin-bottom: 0; color: #fff; font-size: 13px; } .movie-info { position: absolute; top: 0; left: 0; width: 100%; height: 100%; padding: 15px; background: rgba(0, 0, 0, 0.85); opacity: 0; display: flex; flex-wrap: wrap; align-items: center; transition: all .3s; } .movie-info * { width: 100%; display: block; } #ajax_filter_search_results li:hover .movie-info { opacity: 1; } |
BONUS
Tìm kiếm đơn vị cung cấp check box ( Netflix / Amazone / Viki ….)
Bước đầu tiên thêm các trường trong ACF

Bổ sung thêm trường hiển thị trong form
1 2 3 4 |
<input class="available" type="checkbox" id="netflix" value="netflix" name="available"><label for="netflix">Netflix</label> <input class="available" type="checkbox" id="amazon" value="amazon" name="available"><label for="amazon">Amazon</label> <input class="available" type="checkbox" id="viki" value="viki" name="available"><label for="viki">Viki</label> <input class="available" type="checkbox" id="blueray" value="blueray" name="available"><label for="blueray">BlueRay</label> |
Sau đó, hãy thêm phần javascript. Ở đây chúng tôi đang lấy các giá trị của các hộp kiểm vào một mảng.
1 2 3 4 |
var available = []; $.each($("input[name='available']:checked"), function(){ available.push($(this).val()); }); |
Bên trong my_ajax_filter_search_callback()
hàm trước điều kiện meta_query thể loại, hãy thêm một số mã
1 2 3 4 5 6 7 8 9 10 |
if(isset($_GET['available'])) { $available = $_GET['available']; foreach( $available as $value ) { $meta_query[] = array( 'key' => 'available_on', // our new added custom field for the checkboxes 'value' => $value, 'compare' => 'LIKE' ); } } |
Bây giờ xem kết quả:

Ae thông cảm tôi là code không giỏi hành văn diễn giải nó hơi lủng củng, cái này sẽ chỉnh sửa dần dần trong các bài tiếp theo. Thấy hay và ý nghĩa thì ủng hộ bằng cách chia sẻ bài viết hoặc góp ý để hoàn thiện bài viết hơn ….. Cảm ơn A/E đã ủng hộ!