Skip Navigation

[Resolved] Set Dropdown with Unique Years & Filter by Default Selection on Initial Load

This thread is resolved. Here is a description of the problem and solution.

Problem: I would like to create a custom search View that includes a custom select field, where the options are defined by a custom shortcode. When the page first loads, I would like to select one of the filters by default.

Solution: The only documented way to select a filter by default in a parametric search form is to use a URL parameter. Any other solution will require custom code. If you want to use a custom shortcode to define the value options for a wpv-control field, you must first register that custom shortcode in Toolset > Settings > Frontend Content > Third party shortcode arguments.

This support ticket is created 6 years, 6 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 - -
13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 - -

Supporter timezone: America/New_York (GMT-04:00)

This topic contains 13 replies, has 2 voices.

Last updated by webD-3 6 years, 6 months ago.

Assisted by: Christian Cox.

Author
Posts
#844739

First, I'm using the latest beta versions of the toolset plugin's.

I'm hoping you guys can help out. I'm building a schedule/results page and I'm wanting a dropdown menu on the page that automatically displays all the years that exist in the schedule entries, and I'm wanting it to select the most recent year by default when the page initially loads...filtering the results on the initial page load (not only after the dropdown selection has been changed).

Currently, I've been able to get a dropdown put in to filter (but it's requiring the dates entered manually, which would have to be manually entered every year), and have a function that filters, but ONLY after the dropdown is selected. Otherwise, it loads all entries on the first page load, which won't work.

//////////////
// FILTER //
//////////////

[wpv-filter-start hide="false"]
[wpv-filter-controls]
[wpml-string context="wpv-views"]Year:[/wpml-string] [wpv-control url_param="wpv-year" type="select" values="2018,2017," display_values="2018,2017,All"]
[/wpv-filter-controls]
[wpv-filter-end]

///////////////////
// FUNCTION //
///////////////////

add_filter( 'wpv_filter_query', 'year_func', 20, 3 );

function year_func( $query_args, $settings, $view_id ) {
if ( $view_id == 305 && isset($_GET['wpv-year'][0]) && !empty($_GET['wpv-year'][0]) ) {
$star_date = strtotime("01/01/" . $_GET['wpv-year'][0]);
$end_date = strtotime("01/01/" . ($_GET['wpv-year'][0] + 1));
$query_args['meta_query'] = array(
array(
'key' => 'wpcf-game-date',
'value' => array($star_date, $end_date),
'compare' => 'BETWEEN',
),
);
}
return $query_args;
}

#846971

Hi, I can think of a few options here. The main challenge is it's not possible to pre-select a filter in a parametric search without a URL parameter. There is no way around it in the current system, other than writing your own custom JavaScript to control the filters.

1. Always link to this page with a URL parameter. Instead of linking to yoursite.com/yoursearchpage, link to yoursite.com/yoursearchpage?wpv-year=2018 - obviously this is not really ideal.
2. Use custom JavaScript to automatically redirect the User from yoursite.com/yoursearchpage to yoursite.com/yoursearchpage?wpv-year=2018 - also not ideal, but I've helped set this up in the past and it's functional.
3. Use the wpv_filter_query_post_process API to drop all the results if the wpv-year parameter isn't present in the query. This will prevent the problem where all the results are shown until the User selects a year, and is probably more practical than trying to manipulate URLs. However, it will not help you pre-select a year filter. The only way to pre-select a filter in a parametric search form is to use a URL parameter. That being said, here's a code example that can be used to hide all results until the year filter is set:

add_filter( 'wpv_filter_query_post_process', 'drop_empty_search_query_post_process', 10, 3 );
function drop_empty_search_query_post_process( $query, $view_settings, $view_id ) {
    $ids = array(12345);
    if (in_array($view_id, $ids)){
      if (
        // year filter needs to check for not '0' as well as not empty
        ( isset($_GET['wpv-year']) && $_GET['wpv-year'] != '0' )          
      ) {
      } else {
        $query->posts = array();
        $query->found_posts = 0;
        $query->post_count = 0;
      }
    }
    return $query;
}

Replace 12345 with the numeric ID of this View, or a comma-separated list of View IDs. The "if" clause may need to be adjusted if you decide to add any other filters to this View in the future.

More information about this filter API here:
https://toolset.com/documentation/programmer-reference/views-filters/#wpv_filter_query_post_process

#848449

Thanks, Christian. I'll take this a step at a time. First, I'll work on trying to get the dropdown to populate dynamically. I had a thought about how to do this, but it isn't working. It populates the dropdown, but doesn't change the results when the selection is changed.

function etc_get_schedule_years(){
        //I want this array to build from the database, but have created this to test with for now.
	$year_array = array('2018','2017');
	return $year_array;
}

add_shortcode('etc-add-years', 'etc_add_years_array');
function etc_add_years_array(){
	$arr = etc_get_schedule_years();
	$unique_data = array_unique($arr);
	foreach($unique_data as $val){
		$years = $years . $val . ',';
	}
	echo do_shortcode('[wpml-string context="wpv-views"]Year:[/wpml-string][wpv-control url_param="wpv-year" type="select" values="' . $years . '" display_values="' . $years . 'All"]');
}

Inside the view Search and Pagination box:

[wpv-filter-start hide="false"]
[wpv-filter-controls]
[etc-add-years]
[/wpv-filter-controls]
[wpv-filter-end]

#848500

Can I take a look in wp-admin to see how this is set up? Please provide login credentials here and let me know where I can find this View on the front-end of the site.

#848860
Screen Shot 2018-05-07 at 5.39.33 PM.png

Okay the main thing I see is that the select filter isn't being injected correctly. Check out this screenshot of the DOM. You can see that the select tag is not part of a form tag, it's just out there by itself. Normally this happens if you do not add any filters using the GUI - the filter system does not recognize that any filters are displayed, so the entire form tag is not rendered. As a test, insert a text search field in the Filter Editor, then inspect the View. You should see a form tag rendered just before the results, including the text search filter. Your custom select field should also be inserted in the form.

Let me know what you find out.

#856455

Yeah, I was trying to inject the toolset shortcode through a custom shortcode, so I could add the values to it in a function, then place the new [wpml-string] shortcode in with those values. Maybe it's injecting too late and preventing the form tag from generating.

#856851

What if you use the custom shortcode to just return the $years value? the WPML string shortcode and the wpv-control shortcode directly in the filter editor, but use the custom shortcode to provide the values and display values of the wpv-control?

What if you bypass the "Page Shortcode Field" block and put the View shortcode directly in the content of the post? I'm not familiar with this system of including shortcodes, so it's possible it's just adding unnecessary complexity here.

#857954

If I place the [etc-add-years] shortcode inside the Loop Editor, it returns the years like it should. The custom shortcode is currently just set to return a string of years now, like this:

2018,2017

However, if I place the shortcode in the wpv-control as values="[etc-add-years]", it breaks it and doesn't generate the dropdown properly (plus no data is returned to the dropdown either). It might be sending over extra quotation marks or something, since it looks like wpv-control must not have been built to work this way. I also tried changing the view shortcode to:

[wpv-view name="schedule-view" years_var="[etc-add-years]"]

and added values="[wpv-attribute name='years_var']" to the wpv-control, but that didn't work either. The wpv-view apparently wasn't able to process the [etc-add-years] shortcode, because if I manually enter "2018,2017" as the value for "years_var", it passes that over okay and generates the dropdown with those years.

#858121

However, if I place the shortcode in the wpv-control as values="[etc-add-years]", it breaks it and doesn't generate the dropdown properly
Can you confirm you have registered this shortcode in Toolset > Settings > Front-end content > Third-party shortcode arguments?

#858449

Thank you, that is exactly why it wasn't loading the shortcode into the dropdown! I added it to the front-end content settings and it's working now. That solves that part of the issue!

I added your function to display no results on the first page load, and while it does prevent ALL the results from loading, I think it's going to be inconvenient for users to have to enter an empty page and select a year to view those results. Is there a way to tell it to select the top item, if items exist (or maybe pull the top year from an array & give it a specific query on the initial page load), so it always loads the most recent year on the first page load?

#859063

Okay great, that shortcode registration process is easy to forget or overlook.

Is there a way to tell it to select the top item, if items exist (or maybe pull the top year from an array & give it a specific query on the initial page load), so it always loads the most recent year on the first page load?
Yes: use a URL parameter. As I was saying earlier:

The main challenge is it's not possible to pre-select a filter in a parametric search without a URL parameter. There is no way around it in the current system, other than writing your own custom JavaScript to control the filters.

#860066
Capture.JPG

Thanks, Christian, I'll look into writing some javascript to perform that.

Sorry for all the questions, but I have one last thing. I'm having trouble generating an array of years from the database.

The Field Slug is "game-date". It's a custom field inside the Games post type (post-type slug is "game"). Looking at the database, it looks like all the custom fields are an array inside the meta_value, and the meta_key is _wp_types_group_fields. I've attached a screenshot. The post_id is 118 and the meta_id's are 234 (_wp_types_group_fields),235 (_wp_types_group_post_types).

If I can build an array of dates from the database, I should be able to use that array to dynamically display the dates in the dropdown. I was manually creating the array in the function until I got this far and was ready to tackle this part of the task.

#860494

There's not an API available to get all the possible values of a custom field. You could write a custom SQL query. If you select all the unique values for 'wpcf-game-date' in the postmeta table, you'll have all the values for this field, attached to any post. This seems pretty inefficient though, especially if the query is performed every time the page loads. It seems like it would be more practical to just create an array of every possible year back to a certain point in history using PHP, and leave the database query out of it.

#861234

Okay, I'll see what I can figure out. I realize it'll be considered somewhat inefficient, but the site won't receive an unusually large amount of traffic, and each year will receive no more than 15 entries. It will look cleaner than giving options in the dropdown that aren't relevant (since I'd have to enter a large range to make sure enough was covered and we wouldn't have to manually make changes to the range later). I also have to consider they may add results from the past years at some point. If it becomes necessary, I may consider looking into writing a class and session for the dropdown, so it wouldn't have to populate from the database every time. I haven't needed to try anything like that in PHP yet, but I've done that sort of thing in C# plenty, and I assume it's similar.