← Back to Blog

Convert FacetWP Dropdown/Radio into a numeric range 111

FacetWP's default select and radio filters only support exact matches for categories, tags, or custom field values.

Different Requirements

Filter programs where minimum age ≥ 10.
Filter programs where maximum hours ≤ 20.

FacetWP’s dropdown or radio facets cannot perform these numeric comparisons as they only check for equality.

This article discusses converting FacetWP filters into numeric range filters using key hooks.

Numeric Comparison Filtering

FacetWP provides the facetwp_facet_filter_posts hook to change the default filtering behavior.

The code below replaces equality checks with greater than or equal to (≥) or less than or equal to (≤):

Map specific facet names (e.g., program_minimum_age) to comparison operators like >= or <=.
Cast selected values to integers for accurate comparisons.
Dynamically retrieve posts where numeric custom fields meet conditions.

This transforms standard filters into numeric range filters.

Dynamic Counts for Range Facets

FacetWP shows counts based on exact matches (e.g., 10+ (12)). Since we've changed to numeric comparisons, these counts may be inaccurate.

We can fix this by overriding counts with the facetwp_facet_display_value filter:

add_filter('facetwp_facet_display_value', function ($output, $params) {
    global $wpdb;
    $facet = $params['facet'] ?? [];
    $row = $params['row'] ?? [];

    $facet_name = $facet['name'] ?? '';
    $facet_value = $row['facet_value'] ?? '';
    $display_value = $row['facet_display_value'] ?? '';
    $counter = $row['counter'] ?? 0;

    $facet_comparisons = [
        'program_minimum_age'    => '>=',
        'program_minimum_grade'  => '>=',
        'program_minimum_hours'  => '>=',
        'program_maximum_age'    => '<=',
        'program_maximum_grade'  => '<=',
        'program_maximum_hours'  => '<=',
    ];

    if (! isset($facet_comparisons[$facet_name])) {
        return $output;
    }

    $comparison = $facet_comparisons[$facet_name];

    // Calculate dynamic counts
    $table = $wpdb->prefix . 'facetwp_index';
    $sql = $wpdb->prepare(
        "SELECT COUNT(DISTINCT post_id)
        FROM {$table}
        WHERE facet_name = %s AND facet_value {$comparison} %d",
        $facet_name,
        (int) $facet_value
    );

    $count = (int) $wpdb->get_var($sql);

    return sprintf('%s (%d)', $display_value, $count);
}, 10, 2);

Functionality:

Removing Default Counts from Dropdowns

You may want to remove default counts (e.g., (xx)) from dropdowns for clarity.

add_filter('facetwp_facet_html', function ($output, $params) {
    if ('dropdown' === ($params['facet']['type'] ?? '')) {
        // Remove only the final (xx) count from the right
        $output = preg_replace('/\s*\(\d+\)\s*<\/option>/', '</option>', $output);
    }
    return $output;
}, 10, 2);