Bạn muốn tối ưu trải nghiệm người dùng hiển thị giá sản phẩm của biến thể dể nhìn hơn theo giá trị form mặc định thay vì khoảng giá mặc định của Woocommerce và hiển thị thuộc tính biến thế sản phẩm trong vòng lặp ,danh mục sản phẩm.
1.Ở trang shop/category (vòng lặp sản phẩm), bạn muốn hiển thị nhanh kích thước (thuộc tính pa_kich-thuoc) như dạng “nút bấm” (swatch) ngay dưới tiêu đề để khách nhìn là chọn được ngay.
2.Sản phẩm biến thể thường hiển thị giá dạng khoảng min–max (“₫xxx – ₫yyy”), nhưng bạn muốn hiển thị đúng giá của biến thể mặc định (default attributes). Đồng thời khi người dùng click size, giá trên product card phải đổi theo kích thước.
Bài viết này Sơn Web sẽ hướng dẫn bạn code 2 chức năng trên theo logic sau nhé:
✅ In swatch size trong loop
✅ Tự active size mặc định
✅ Click kích thước đổi giá ngay trong vòng lặp sản phẩm
✅ Fix theme Flatsome hay bị show min–max lúc load
✅ Filter để loop hiển thị giá theo biến thể mặc định
1.Hiển thị nút kích thước dưới tiêu đề trong vòng lặp (Shop/Category)
Bước 1: Sử dụng hook add_action( ‘woocommerce_after_shop_loop_item’, ‘hien_thi_pa_kich_thuoc_loop’, 9 );
Vì sao dùng hook này phù hợp?
- woocommerce_after_shop_loop_item chạy ngay trong mỗi product card của loop
- Priority 9 giúp bạn kiểm soát vị trí hiển thị sớm/trước các phần khác (tùy theme sử dụng)
Logic code xử lý trong hàm hien_thi_pa_kich_thuoc_loop()
Bước 1: Lấy $product sử dụng global $product;
Bước 2: Chặn các sản phẩm không phải biến thể
Bước 3: Kiểm tra các sản phẩm có thuộc tính pa_kich-thuoc không
$attributes = $product->get_attributes(); if ( ! array_key_exists( 'pa_kich-thuoc', $attributes ) ) return;
Bước 4: Lấy danh sách variations để in ra các nút
$variations = $product->get_available_variations(); if ( empty( $variations ) ) return;
Bước 5: Lấy giá trị mặc định của sản phẩm có giá thuộc tính kích thước
$default_attributes = $product->get_default_attributes(); $default_size = isset($default_attributes['pa_kich-thuoc']) ? $default_attributes['pa_kich-thuoc'] : '';
Bước 6: Hiển thị các nút kích thước
Mỗi nút là
Gắn data-price-html để JS lấy và thay giá
Nếu slug size trùng default → thêm class active
Kết quả HTML hiển thị kiểu:
<div class="gb-size-swatch"> <span class="gb-size-item active" data-price-html="...">M</span> <span class="gb-size-item" data-price-html="...">L</span> </div>
Toàn bộ code hiển thị nút kích thước trong loop
// 1) In nút size dưới title trong loop
add_action( 'woocommerce_after_shop_loop_item', 'hien_thi_pa_kich_thuoc_loop', 9 );
function hien_thi_pa_kich_thuoc_loop() {
global $product;
if ( ! $product->is_type( 'variable' ) ) return;
$attributes = $product->get_attributes();
if ( ! array_key_exists( 'pa_kich-thuoc', $attributes ) ) return;
$variations = $product->get_available_variations();
if ( empty( $variations ) ) return;
// --- LẤY GIÁ TRỊ MẶC ĐỊNH ---
$default_attributes = $product->get_default_attributes();
$default_size = isset($default_attributes['pa_kich-thuoc']) ? $default_attributes['pa_kich-thuoc'] : '';
echo '<div class="gb-size-swatch">';
foreach ( $variations as $variation ) {
$attr_key = 'attribute_pa_kich-thuoc';
if ( isset( $variation['attributes'][$attr_key] ) ) {
$size_slug = $variation['attributes'][$attr_key];
$size_name = str_replace('-', ' ', $size_slug);
$price_html = $variation['price_html'];
// Kiểm tra xem size này có phải là size mặc định không
// Nếu đúng hoặc nếu không có mặc định thì active cái đầu tiên (tùy chọn)
$active_class = ($size_slug == $default_size) ? 'active' : '';
printf(
'<span class="gb-size-item %s" data-price-html="%s" title="%s">%s</span>',
esc_attr( $active_class ), // Thêm class active vào đây
esc_attr( $price_html ),
esc_attr( ucfirst($size_name) ),
esc_html( ucfirst($size_name) )
);
}
}
echo '</div>';
}
2.JS đổi giá theo Size & tự chạy khi load trang (fix lỗi min–max của Flatsome)
2.1 Bạn gắn script ở footer với code sau: add_action( ‘wp_footer’, ‘sonweb_script_fix_price_flatsome’ );
2.2 Sử dụng hàm đổi giá dùng chung updateProductPrice($btn)
function updateProductPrice($btn) {
var newPriceHtml = $btn.attr('data-price-html');
var $productCard = $btn.closest('.product-small, .col-inner, .product');
var $priceElement = $productCard.find('.price').first();
if ( newPriceHtml && $priceElement.length ) {
$priceElement.html( newPriceHtml );
}
}
Giải thích cơ bản:
$btn là nút size người dùng click
Lấy data-price-html (đã được PHP in ra từ $variation[‘price_html’])
Dò ngược lên card sản phẩm bằng .closest(…) (phù hợp nhiều layout Flatsome)
Tìm .price và thay HTML
đây là toàn bộ code js
add_action( 'wp_footer', 'sonweb_script_fix_price_flatsome' );
function sonweb_script_fix_price_flatsome() {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
// HAM XU LY DOI GIA (Dung chung)
function updateProductPrice($btn) {
var newPriceHtml = $btn.attr('data-price-html');
// Selector tim gia trong Flatsome (.price-wrapper .price)
var $productCard = $btn.closest('.product-small, .col-inner, .product');
var $priceElement = $productCard.find('.price').first();
if ( newPriceHtml && $priceElement.length ) {
$priceElement.html( newPriceHtml );
}
}
// 1. SU KIEN CLICK (Nhu cu)
$(document).on('click', '.gb-size-item', function(e) {
e.preventDefault();
e.stopPropagation();
var $this = $(this);
// UX: Doi class active
$this.siblings().removeClass('active');
$this.addClass('active');
// Goi ham doi gia
updateProductPrice($this);
});
// 2. TU DONG CHAY KHI LOAD TRANG (Fix loi Flatsome hien Min-Max)
// Tim tat ca cac nut dang co class 'active' (do PHP in ra tu form mac dinh)
$('.gb-size-item.active').each(function() {
updateProductPrice($(this));
});
});
</script>
<?php
}
2.3 bắt sự kiện click trên .gb-size-item
$(document).on('click', '.gb-size-item', function(e) {
e.preventDefault();
e.stopPropagation();
var $this = $(this);
$this.siblings().removeClass('active');
$this.addClass('active');
updateProductPrice($this);
});
2.4 Tự đổi giá sản phẩm khi load trang (đúng biến thể mặc định)
$('.gb-size-item.active').each(function() {
updateProductPrice($(this));
});
Code này chính là hỗ trợ fix theme Flatsome hay hiện min–max lúc vừa load.
Vì PHP đã in ra class active theo default, JS chỉ việc đọc data-price-html và replace.
Toàn bộ code
/**
* Single + Loop: Hiển thị giá Variable theo biến thể mặc định (Default form values)
* thay vì giá dạng khoảng (min-max).
*/
add_filter( 'woocommerce_variable_price_html', 'hien_thi_gia_mac_dinh_trong_loop', 20, 2 );
function hien_thi_gia_mac_dinh_trong_loop( $price, $product ) {
// Chỉ chạy ở trang Loop (Danh mục, Cửa hàng), không chạy trong trang chi tiết
// Nếu muốn chạy cả trang chi tiết thì bỏ dòng if ( ! is_shop... ) đi
if ( ! is_shop() && ! is_product_category() && ! is_product_tag() ) {
// return $price; // Bỏ comment dòng này nếu muốn giữ nguyên ở trang chi tiết
}
if ( ! $product->is_type( 'variable' ) ) return $price;
// Lấy các thuộc tính mặc định đã set trong admin
$default_attributes = $product->get_default_attributes();
// Nếu KHÔNG set mặc định thì giữ nguyên giá range (min - max)
if ( empty( $default_attributes ) ) {
return $price;
}
// Tìm ID của biến thể khớp với thuộc tính mặc định
try {
$data_store = WC_Data_Store::load( 'product' );
$variation_id = $data_store->find_matching_product_variation( $product, $default_attributes );
if ( $variation_id ) {
$variation = wc_get_product( $variation_id );
if ( $variation ) {
// Trả về HTML giá của biến thể mặc định
return $variation->get_price_html();
}
}
} catch ( Exception $e ) {
return $price;
}
return $price;
}
Fix hiển thị giá Variable trong loop theo biến thể mặc định
Gợi ý CSS để nút size nhìn đẹp (nhẹ, hợp Flatsome)
Bạn có thể thêm nhanh code sau vào Custom CSS trong admin:
.gb-size-swatch{
display:flex;
gap:6px;
flex-wrap:wrap;
margin-top:8px;
}
.gb-size-item{
display:inline-flex;
align-items:center;
justify-content:center;
padding:4px 10px;
border:1px solid rgba(0,0,0,.15);
border-radius:999px;
font-size:12px;
cursor:pointer;
user-select:none;
}
.gb-size-item.active{
border-color: rgba(0,0,0,.6);
font-weight:600;
}
