How to add custom filters like date range in post list admin area

How to Add Custom Filters like Date Range in Posts List Admin Area

Almost every part of the WordPress core can be modified using hooks. They can be added to your plugin or a theme and can be used to change how WordPress displays data. If you are new to hooks, here is a whole article about them explaining how they interact with WordPress. We’ll use hooks as well to modify the posts list in the admin area. We suggest adding this functionality to a plugin.

Home / Blog / Unspecified / How to Add Custom Filters like Date Range in Posts List Admin Area

Table of Contents

Almost every part of the WordPress core can be modified using hooks. They can be added to your plugin or a theme and can be used to change how WordPress displays data. If you are new to hooks, here is a whole article about them explaining how they interact with WordPress. We’ll use hooks as well to modify the posts list in the admin area. We suggest adding this functionality to a plugin.

Let’s get started.

Hooks we need

  • restrict_manage_posts
  • pre_get_posts
  • admin_enqueue_scripts

We’ll use the restrict_manage_posts to create the field for filtering. The second hook we’ll be used for filtering the posts, and the third one we’ll be used to include the jquery-ui-datepicker script because it is not automatically included in the admin area.

If successful, the posts list should look something like this:

The code

In your main plugin or a theme file add these hooks (it is up to you how you would like to structure your plugin):

<?php

add_action( 'restrict_manage_posts', 'form_select' );
add_action( 'pre_get_posts', 'query_filter' );
add_action( 'admin_enqueue_scripts', 'jqueryui' );

Create a function (or a method if you are using a class) for each callback:

<?php

function form_select() {
    $post_type = (isset($_GET['post_type'])) ? $_GET['post_type'] : 'post';

    if ($post_type == 'post') {
	// please use unique name
	$from = ( isset( $_GET['pe_date'] ) && $_GET['pe_date'] ) ? $_GET['pe_date'] : '';

	echo '<input type="text" name="pe_date" placeholder="Date From" value="' . esc_attr( $from ) . '" />
		
		   <script>
		      jQuery( function($) {
			  let from = $(\'input[name="pe_date"]\');

			  // the dates look like this "April 3, 2017" by default
			  // you can schoose something different, for example
			  from.datepicker( {dateFormat : "yy-mm-dd"} );
			
		     });
		   </script>';
     } // end if
}

You can include the filter in any post type you want.

function query_filter( $admin_query ) {
	global $pagenow;
	$post_type = (isset($_GET['post_type'])) ? $_GET['post_type'] : 'post';

	if ( $post_type == 'post' && $pagenow == 'edit.php' && isset( $_GET['pe_date'] ) && !empty( $_GET['pe_date'] ) ) {
		$admin_query->set(
			'date_query', // date_query appeared in WordPress 3.7!
			array(
				'after' => sanitize_text_field( $_GET['pe_date'] ),
				'before' => sanitize_text_field( $_GET['pe_date'] ),
				'inclusive' => true, // include the selected days as well
				'column' => 'post_date' // 'post_modified', 'post_date_gmt', 'post_modified_gmt'
			)
		);
	}

	return $admin_query;
}

Do the filtering by date only if the custom post type is post, if we are on the edit page, and if the pe_date field is not empty.

<?php

function jqueryui () {
	wp_enqueue_style( 'pe-jquery-ui', '//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.min.css' );
	wp_enqueue_script( 'jquery-ui-datepicker' );
}

Include the script and the styling for the datepicker.

This is it. Now, let’s make things more interesting and add another filter that will display the posts by status.

Tweak the form_select function like this:

function form_select() {
	$post_type = ( isset($_GET['post_type']) ) ? $_GET['post_type'] : 'post';

	if ($post_type == 'post') {
		// please use unique name
		$from = ( isset( $_GET['pe_date'] ) && $_GET['pe_date'] ) ? $_GET['pe_date'] : '';
		$current_status = $_GET['pe_status'] ?? '';
		$statuses = get_post_statuses();

		echo '<input type="text" name="pe_date" placeholder="Date From" value="' . esc_attr( $from ) . '" />';

		?>

		<select name="pe_status">
			<option value=""><?= __('All statuses', 'projectsengine'); ?></option>

			<?php

			foreach ($statuses as $key => $status) {
				printf(
					'<option value="%s"%s>%s</option>',
					$key,
					$key == $current_status ? ' selected="selected"' : '',
					$status
				);
			}
			?>
		</select>

		<?php


		echo '<script>
		jQuery( function($) {
			let from = $(\'input[name="pe_date"]\');
	
			// the dates look like this "April 3, 2017" by default
			// you can schoose something different, for example
			from.datepicker( {dateFormat : "yy/mm/dd"} );
			
		});
		</script>';
	}
}

get_post_statuses() will return all of the statuses that are currently registered on your website. Add them as options to a select field.

Tweak the query_filter function like this:

function query_filter( $admin_query ) {
	global $pagenow;
	$post_type = (isset($_GET['post_type'])) ? $_GET['post_type'] : 'post';

	if ( $post_type == 'post' && $pagenow == 'edit.php' ) {
		if ( isset( $_GET['pe_status'] ) && ! empty( $_GET['pe_status'] ) ) {
			$admin_query->set('post_status', $_GET['pe_status'] );
		}

		if ( isset( $_GET['pe_date'] ) && ! empty( $_GET['pe_date'] ) ) {
			$admin_query->set(
				'date_query', // date_query appeared in WordPress 3.7!
				array(
					'after'     => sanitize_text_field( $_GET['pe_date'] ),
					'before'    => sanitize_text_field( $_GET['pe_date'] ),
					'inclusive' => true, // include the selected days as well
					'column'    => 'post_date' // 'post_modified', 'post_date_gmt', 'post_modified_gmt'
				)
			);
		}
	}

	return $admin_query;
}

We’ll modify the posts query only if the fields/filters are not empty.

Comments

At the moment, there are 2 comments for this post.

restrict_manage_users and pre_user_query might be useful. -
Hi how do i implement this filter to a WP_List_Table since as WP_List_Table is a done as plugin with a date registration field? So I am trying to filter the user_registered by date admin.php?page=employees_list_table and not edit.php?post_type=advert as normal post in wordpress -