Chào các bạn, đã rất lâu rồi mình mới sắp xếp được thời gian hướng dẫn cho mọi người tiếp khóa lập trình theme Woocommerce. Bài ngày hôm nay mình sẽ hướng dẫn các bạn từng bước thực thi:
À mà quên, các bạn nhớ thêm class tên like-btn và data id vào nút add to wishlist nha. Ở đây mình thêm vào phần template loop của add-to-cart.php
<button class="like-btn" data-id="%s" title="Add to Wishlist"><i class="icon-heart-empty"></i></button>
Bước 1: Viết code Javascript để xử lý like/unlike và lưu danh sách ID sản phẩm đã like vào local storage
jQuery(document).ready(function ($) {
const STORAGE_KEY = 'whc_liked_products';
// Hàm lấy danh sách ID đã thích từ Local Storage
function getLikedProducts() {
const data = localStorage.getItem(STORAGE_KEY);
return data ? JSON.parse(data) : [];
}
// Hàm cập nhật trạng thái icon khi load trang
function updateIconsOnLoad() {
const likedIds = getLikedProducts();
$('.like-btn').each(function () {
const id = $(this).data('id');
const icon = $(this).find('i');
if (likedIds.includes(id)) {
icon.removeClass('icon-heart-empty').addClass('icon-heart');
} else {
icon.removeClass('icon-heart').addClass('icon-heart-empty');
}
});
}
// Chạy kiểm tra ngay khi trang web tải xong
updateIconsOnLoad();
// Xử lý sự kiện Click
$(document).on('click', '.like-btn', function (e) {
e.preventDefault();
const _this = $(this);
const icon = _this.find('i');
const productId = _this.data('id');
let likedIds = getLikedProducts();
const index = likedIds.indexOf(productId);
if (index > -1) {
// Nếu đã có trong danh sách -> Xóa đi (Unlike)
likedIds.splice(index, 1);
icon.removeClass('icon-heart').addClass('icon-heart-empty');
} else {
// Nếu chưa có -> Thêm vào (Like)
likedIds.push(productId);
icon.removeClass('icon-heart-empty').addClass('icon-heart');
}
// Lưu mảng mới vào Local Storage
localStorage.setItem(STORAGE_KEY, JSON.stringify(likedIds));
});
});
Bước 2: Tạo 1 template cho trang Wishlist để hiển thị danh sách các sản phẩm được like và bao gồm xử lý code khi người dùng bấm vào nút remove item:
<?php
/* Template Name: Wishlist */
get_header();
?>
<div class="breadcrumb-area breadcrumb-mt breadcrumb-ptb-2">
<div class="container">
<div class="breadcrumb-content">
<h2>Wishlist</h2>
<ul>
<li><a href="<?php echo home_url(); ?>">Home</a></li>
<li><span> > </span></li>
<li><a href="<?php echo get_post_type_archive_link('product'); ?>">Product</a></li>
<li><span> > </span></li>
<li class="active"> Wishlist </li>
</ul>
</div>
</div>
</div>
<div class="cart-area bg-gray pt-160 pb-160">
<div class="container">
<div id="wishlist-empty-message" style="display:none; text-align:center;">
<h3>Danh sách yêu thích của bạn đang trống.</h3>
<a href="<?php echo get_post_type_archive_link('product'); ?>" class="btn btn-primary">Tiếp tục mua sắm</a>
</div>
<div id="wishlist-content" class="cart-table-content wishlist-wrap">
<div class="table-content table-responsive">
<table>
<thead>
<tr>
<th>Product</th>
<th class="th-text-center">Price</th>
<th class="th-text-center">Stock Status</th>
<th class="th-text-center">Add To Cart</th>
<th class="th-text-center">Remove</th>
</tr>
</thead>
<tbody id="wishlist-table-body">
<tr class="loading-placeholder">
<td colspan="5" style="text-align:center; padding: 50px;">
<div class="spinner"></div> Đang tải danh sách yêu thích...
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script>
jQuery(document).ready(function($) {
const STORAGE_KEY = 'whc_liked_products';
const likedIds = JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
if (likedIds.length === 0) {
$('#wishlist-content').hide();
$('#wishlist-empty-message').show();
return;
}
// Gửi AJAX để lấy thông tin sản phẩm dựa trên ID từ Local Storage
$.ajax({
url: '<?php echo admin_url('admin-ajax.php'); ?>',
type: 'POST',
data: {
action: 'get_wishlist_products',
ids: likedIds
},
success: function(response) {
if (response.success) {
$('#wishlist-table-body').html(response.data);
}
}
});
// Xử lý xóa sản phẩm khỏi Wishlist ngay tại trang này
$(document).on('click', '.remove-wishlist', function(e) {
e.preventDefault();
const id = $(this).data('id');
let currentIds = JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
currentIds = currentIds.filter(item => item !== id);
localStorage.setItem(STORAGE_KEY, JSON.stringify(currentIds));
$(this).closest('tr').fadeOut(300, function() {
if (currentIds.length === 0) location.reload();
});
});
});
</script>
<?php get_footer(); ?>
Bước 3: Xây dựng câu truy vấn ở backend thông qua ajax để hiển thị danh sách sản phẩm và trả kết quả lại cho phía frontend:
add_action('wp_ajax_get_wishlist_products', 'tn_get_wishlist_products');
add_action('wp_ajax_nopriv_get_wishlist_products', 'tn_get_wishlist_products');
function tn_get_wishlist_products() {
$ids = isset($_POST['ids']) ? array_map('intval', $_POST['ids']) : array();
if (empty($ids)) {
wp_send_json_error('No products found');
}
$args = array(
'post_type' => 'product',
'post__in' => $ids,
'posts_per_page' => -1,
'orderby' => 'post__in'
);
$query = new WP_Query($args);
$html = '';
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$product = wc_get_product(get_the_ID());
$html .= '<tr>';
$html .= '<td class="cart-product">
<div class="product-img-info-wrap">
<div class="product-img">
<a href="'.get_permalink().'">'.get_the_post_thumbnail(get_the_ID(), 'thumbnail').'</a>
</div>
<div class="product-info">
<h4><a href="'.get_permalink().'">'.get_the_title().'</a></h4>
</div>
</div>
</td>';
$html .= '<td class="product-price"><span class="amount">'.$product->get_price_html().'</span></td>';
$html .= '<td class="th-text-center">'.($product->is_in_stock() ? 'Còn hàng' : 'Hết hàng').'</td>';
$html .= '<td class="product-wishlist-cart">
<a href="'.get_permalink().'">Add To Cart</a>
</td>';
$html .= '<td class="th-text-center">
<a href="#" class="remove-wishlist" data-id="'.get_the_ID().'">❌</a>
</td>';
$html .= '</tr>';
}
wp_reset_postdata();
}
wp_send_json_success($html);
}
Chúc các bạn thực hành thành công, nhớ đăng ký hội viên Pro để học chỉ với 60k/1 tháng để ủng hộ mình nha.