is it possible to add “extra” table nav to edit-tags.php screens?

I’ve been searching around for the same answer to your question and running into the exact same issues, and really appreciate your thorough research. I’m definitely +1 here for proposing this addition!

To attempt to answer 2) – I don’t think there’s a good reason to exclude it. I think WordPress’s taxonomy terms are woefully lacking in features compared to the post and user entities (seeing as how term meta came much later, after post and user meta), and would like to see that change.

To answer 1) – I don’t know how much better this is than your solution, but the workaround I’ve come up with involves filtering the taxonomy list via the get_terms_args filter, and then manually inserting a select dropdown + filter button in client-side JS. Here’s a sample of my setup (modified to not use my specific classes or constants), which is filtering by a certain term meta field:

PHP Logic

// @see https://developer.wordpress.org/reference/hooks/get_terms_args/
add_filter( 'get_terms_args', 'taxonomy_filter', 10, 2 );

function taxonomy_filter( $args, $taxonomies ) {
    global $pagenow;
    if ( 'edit-tags.php' !== $pagenow || ! in_array( 'taxonomy-name', $taxonomies, true ) ) { return $args; }

    // Sort by most recently added terms, instead of alphabetically
    $args['orderby'] = 'term_id';
    $args['order'] = 'desc';

    // Filter by term meta
    $meta_key = ( isset( $_GET['meta_key'] ) ) ? sanitize_text_field( $_GET['meta_key'] ) : null;
    $meta_value = ( isset( $_GET['meta_value'] ) ) ? sanitize_text_field( $_GET['meta_value'] ) : null;

    if ( 'meta-filter' === $meta_key && $meta_value ) {
        $args['meta_key'] = $meta_key;
        $args['meta_value'] = $meta_value;
    }

    // Note: for more complex filtering, use the $args['meta_query'] array.

    return $args;
}

At this point, you should be able to see this working simply by going to (e.g.) yoursite.com/wp-admin/edit-tags.php?taxonomy=taxonomy-name&meta_key=meta-filter&meta_value=foobar.

Client-side jQuery logic

(Make sure you include this file in wp_enqueue_script(), but only when $pagenow === 'edit-tags.php').

/**
 * Param helpers
 */

// Get params in a JS object
var params = {};
window.location.search.substr(1).split( '&' ).forEach(function(item) {
    params[ item.split( '=' )[0] ] = item.split( '=' )[1];
});

// Return param string based on the params object
function setParams() {
    var string = '?';

    for ( key in params ) {
        var value = params[ key ];
        string += key + '=' + value + '&';
    }

    return string.slice(0, -1); // Remove trailing &
}

/**
 * Add dropdown filters + functionality to term tables
 */

if ( 'taxonomy-name' === params.taxonomy ) {
    // Create the dropdown menu & HTML
    $( document.querySelector( '.tablenav .bulkactions' ) ).after( '\
        <div class="alignleft actions"> \
            <select id="js-filter-dropdown"> \
                <option value="">Term Meta Filter</option> \
                <option value="foo">Foo</option> \
                <option value="bar">Bar</option> \
                <option value="baz">Baz</option> \
            </select> \
            <button id="js-filter" class="button" type="button">Filter</button> \
        </div> \
    ' );

    // If we're already filtering the view, have the dropdown reflect that
    var value = decodeURIComponent( params.meta_value ).replace(/\+/g, ' ');
    $( '#js-filter-dropdown' ).find( 'option[value="' + value + '"]' ).prop( 'selected', true );

    // Set up the button action - see taxonomy_filter() for server-side filtering
    $( '#js-filter' ).click(function() {
        var value = $( '#js-filter-dropdown' ).val();

        if ( value ) {
            params.meta_key = 'meta-filter';
            params.meta_value = encodeURIComponent( value );
        } else {
            delete params.meta_key;
            delete params.meta_value;
        }

        window.location.search = setParams();
    });
}

Screenshot of the Filtering UI

Before

Screenshot of the filtered table

After image

Leave a Comment