This is a functionality to be active in admin panel. and yes I need to fetch the items in front end the same order. Well here is what I have tried so far.
Custom post and taxonomy added in ACF. Hirarcy enabled. Sortable enabled.
add_action('admin_enqueue_scripts', function($hook) {
if ($hook === 'edit-tags.php' && $_GET['taxonomy'] === 'condition') {
wp_enqueue_script('jquery-ui-sortable');
wp_enqueue_script('condition-sort', get_stylesheet_directory_uri() . '/js/taxonomy-sort.js', array('jquery', 'jquery-ui-sortable'), false, true);
wp_localize_script('condition-sort', 'cts', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('condition_sort_nonce')
]);
} });
// Add custom column
add_filter('manage_edit-condition_columns', function($columns) {
$columns['order'] = '';
return $columns;
});
// Display sort handle
add_filter('manage_condition_custom_column', function($content, $column_name, $term_id) {
if ($column_name === 'order') {
return '<span class="handle">≡</span>';
}
return $content;
}, 10, 3);
add_action('wp_ajax_save_condition_order', function() {
check_ajax_referer('condition_sort_nonce', 'nonce');
if (!current_user_can('manage_categories') || !isset($_POST['order'])) {
wp_send_json_error();
}
$order = $_POST['order'];
foreach ($order as $index => $term_id) {
update_term_meta($term_id, 'custom_order', $index);
}
wp_send_json_success();
});
add_filter('get_terms_orderby', function($orderby, $args) {
if (!is_admin() && isset($args['taxonomy']) && $args['taxonomy'] === 'condition') {
return "CAST((SELECT meta_value FROM wp_termmeta WHERE term_id = t.term_id AND meta_key = 'custom_order') AS UNSIGNED)";
}
return $orderby;
}, 10, 2);
My Custom taxonomy name is "condition". Post type is "sea-foods".
Here is the js I use.
jQuery(document).ready(function($) {
$('tbody').sortable({
handle: '.handle',
update: function() {
let order = [];
$('tbody tr').each(function() {
order.push($(this).attr('id').replace('tag-', ''));
});
$.post(cts.ajax_url, {
action: 'save_condition_order',
order: order,
nonce: cts.nonce
}, function(response) {
if (response.success) {
console.log('Order saved');
} else {
alert('Failed to save order');
}
});
}
});
});
The problem is, the drag and drop working. In the console I am getting the order saved notice. But the order is not actually get saved. May be I am doing something wrong in the updatae meta section or something in the saving the order part.
Any help will be appriciated.
This is a functionality to be active in admin panel. and yes I need to fetch the items in front end the same order. Well here is what I have tried so far.
Custom post and taxonomy added in ACF. Hirarcy enabled. Sortable enabled.
add_action('admin_enqueue_scripts', function($hook) {
if ($hook === 'edit-tags.php' && $_GET['taxonomy'] === 'condition') {
wp_enqueue_script('jquery-ui-sortable');
wp_enqueue_script('condition-sort', get_stylesheet_directory_uri() . '/js/taxonomy-sort.js', array('jquery', 'jquery-ui-sortable'), false, true);
wp_localize_script('condition-sort', 'cts', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('condition_sort_nonce')
]);
} });
// Add custom column
add_filter('manage_edit-condition_columns', function($columns) {
$columns['order'] = '';
return $columns;
});
// Display sort handle
add_filter('manage_condition_custom_column', function($content, $column_name, $term_id) {
if ($column_name === 'order') {
return '<span class="handle">≡</span>';
}
return $content;
}, 10, 3);
add_action('wp_ajax_save_condition_order', function() {
check_ajax_referer('condition_sort_nonce', 'nonce');
if (!current_user_can('manage_categories') || !isset($_POST['order'])) {
wp_send_json_error();
}
$order = $_POST['order'];
foreach ($order as $index => $term_id) {
update_term_meta($term_id, 'custom_order', $index);
}
wp_send_json_success();
});
add_filter('get_terms_orderby', function($orderby, $args) {
if (!is_admin() && isset($args['taxonomy']) && $args['taxonomy'] === 'condition') {
return "CAST((SELECT meta_value FROM wp_termmeta WHERE term_id = t.term_id AND meta_key = 'custom_order') AS UNSIGNED)";
}
return $orderby;
}, 10, 2);
My Custom taxonomy name is "condition". Post type is "sea-foods".
Here is the js I use.
jQuery(document).ready(function($) {
$('tbody').sortable({
handle: '.handle',
update: function() {
let order = [];
$('tbody tr').each(function() {
order.push($(this).attr('id').replace('tag-', ''));
});
$.post(cts.ajax_url, {
action: 'save_condition_order',
order: order,
nonce: cts.nonce
}, function(response) {
if (response.success) {
console.log('Order saved');
} else {
alert('Failed to save order');
}
});
}
});
});
The problem is, the drag and drop working. In the console I am getting the order saved notice. But the order is not actually get saved. May be I am doing something wrong in the updatae meta section or something in the saving the order part.
Any help will be appriciated.
Share Improve this question asked May 10 at 5:18 BehemothBehemoth 1146 bronze badges2 Answers
Reset to default 1Your setup is almost correct! The drag-and-drop works, AJAX fires, and PHP receives the order. The main issue is likely with how you save and retrieve the order.
1. Saving the Order
Your code for saving order with update_term_meta($term_id, 'custom_order', $index);
is correct.
Tip: Check your wp_termmeta
table after sorting to confirm that custom_order
is being set.
foreach ($order as $index => $term_id) {
update_term_meta($term_id, 'custom_order', $index);
error_log("Set order $index for term $term_id");
}
2. Retrieving the Order
Your get_terms_orderby
filter is only running on the frontend (!is_admin()
). Remove that check so the order applies everywhere, including the admin panel.
add_filter('get_terms_orderby', function($orderby, $args) {
if (isset($args['taxonomy']) && $args['taxonomy'] === 'condition') {
global $wpdb;
return "(SELECT meta_value FROM $wpdb->termmeta WHERE term_id = t.term_id AND meta_key = 'custom_order')+0 ASC";
}
return $orderby;
}, 10, 2);
The +0
ensures the sorting is numeric.
3. Fetching Terms in Custom Order
When you fetch terms (front or admin), use 'orderby' => 'custom_order'
:
$terms = get_terms([
'taxonomy' => 'condition',
'orderby' => 'custom_order',
'hide_empty' => false,
]);
4. Extra Tips
- Flush object cache if you use one.
- Add error logging in your PHP handler if needed.
5. Full Working Example
AJAX Handler
add_action('wp_ajax_save_condition_order', function() {
check_ajax_referer('condition_sort_nonce', 'nonce');
if (!current_user_can('manage_categories') || !isset($_POST['order'])) {
wp_send_json_error();
}
$order = $_POST['order'];
foreach ($order as $index => $term_id) {
update_term_meta($term_id, 'custom_order', $index);
}
wp_send_json_success();
});
Orderby Filter
add_filter('get_terms_orderby', function($orderby, $args) {
if (isset($args['taxonomy']) && $args['taxonomy'] === 'condition') {
global $wpdb;
return "(SELECT meta_value FROM $wpdb->termmeta WHERE term_id = t.term_id AND meta_key = 'custom_order')+0 ASC";
}
return $orderby;
}, 10, 2);
6. Debug Checklist
- Check
wp_termmeta
forcustom_order
after sorting. - Ensure your filter runs in both admin and frontend.
- Confirm
get_terms()
uses'orderby' => 'custom_order'
.
7. If Still Not Working
- Try manually updating a term's meta in the DB and see if the order changes.
- Check for JavaScript or network errors in your browser console.
- Make sure your browser cache isn't interfering.
Summary
You are saving the order correctly, but your orderby
filter is only running on the frontend. Remove the !is_admin()
check, and ensure your admin table is using the custom_order
meta for sorting. Also, double-check that the meta is actually being saved in the database.
add_action('admin_enqueue_scripts', function($hook) {
if ($hook === 'edit-tags.php' && $_GET['taxonomy'] === 'condition') {
wp_enqueue_script('jquery-ui-sortable');
wp_enqueue_script('condition-sort', get_stylesheet_directory_uri() . '/js/taxonomy-sort.js', array('jquery', 'jquery-ui-sortable'), false, true);
wp_localize_script('condition-sort', 'cts', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('condition_sort_nonce')
]);
}
});
// Add custom column
add_filter('manage_edit-condition_columns', function($columns) {
$columns['order'] = '';
return $columns;
});
// Display sort handle
add_filter('manage_condition_custom_column', function($content, $column_name, $term_id) {
if ($column_name === 'order') {
return '<span class="handle" data-id="'.$term_id.'">≡</span>';
}
return $content;
}, 10, 3);
add_action('wp_ajax_save_condition_order', function() {
check_ajax_referer('condition_sort_nonce', 'nonce');
if (!current_user_can('manage_categories') || !isset($_POST['order'])) {
wp_send_json_error();
}
$order = $_POST['order'];
//error_log('Received order: ' . print_r($order, true));
foreach ($order as $index => $term_id) {
update_term_meta($term_id, 'custom_order', $index);
//error_log("Set order $index for term $term_id");
}
wp_send_json_success();
});
add_filter('get_terms_orderby', function($orderby, $args) {
if (isset($args['taxonomy'][0]) && $args['taxonomy'][0] === 'condition') {
global $wpdb;
//return "CAST((SELECT meta_value FROM wp_termmeta WHERE term_id = t.term_id AND meta_key = 'custom_order') AS UNSIGNED)";
return "(SELECT meta_value FROM $wpdb->termmeta WHERE term_id = t.term_id AND meta_key = 'custom_order')";
}
return $orderby;
}, 10, 2);
The js code:
jQuery(document).ready(function($) {
$('tbody').sortable({
handle: '.handle',
update: function() {
let order = [];
$('tbody tr').each(function() {
let id = $(this).find('.handle').data('id');
if (id) order.push(id);
});
console.log('Sorted order:', order); // Debug
$.post(cts.ajax_url, {
action: 'save_condition_order',
order: order,
nonce: cts.nonce
}, function(response) {
if (response.success) {
console.log('Order saved');
// Optionally reload: location.reload();
} else {
alert('Failed to save order');
}
});
}
});
});
Its now working. The "Arizona Web Development" who made me correct. Marking it as an answer. Thanks.