I'm tasked with creating a Year filter for our press releases page. We're using the Article
content type, to which we've added a field called Release Date
.
We have the press releases as a block display of a view of articles. Using this question, I was able to add a contextual filter that would accept a four-digit year.
Now I need to make the UI widget for the user to specify the year to filter on. I want it to be populated by the Release Dates
of the article nodes, so that we automatically have all the years appearing in the filter, and don't have to manually add a new one when a new year rolls around.
However I'm having difficulty finding how to get the distinct values of the year part of the Release Date
date field. I've created a display of just the release date field, and set the "Date format" to HTML Year (2019)
. I added aggregation, and for the Aggregation settings of the field, the "Aggregation type" is Group results together
, and the "Group Column" is Value
. I've also set checked Distinct
in query settings.
However, when I look at the preview, I see a number of repetitions of the year. When I add in the full Release Date
field, I see that I am getting one year per distinct date in that year. It seems that the query is pulling each unique date (which is all Article nodes-- none of them share a date), and then doing the formatting (to show only the year) after the select has been performed.
I looked at the Query preview, and it seems that this is indeed what is happening:
GROUP BY node_field_data.nid, node__field_release_date_field_release_date_value, node_field_data_created
I don't understand why it's grouping first by nid, and then also the created date at the end.
FWIW here is the entire query:
SELECT DISTINCT node__field_release_date.field_release_date_value AS node__field_release_date_field_release_date_value, node_field_data.created AS node_field_data_created, node_field_data.nid AS nid, MIN(node_field_data.nid) AS nid_1
FROM
{node_field_data} node_field_data
LEFT JOIN {node__field_release_date} node__field_release_date ON node_field_data.nid = node__field_release_date.entity_id AND node__field_release_date.deleted = '0'
WHERE (node_field_data.status = '1') AND (node_field_data.type IN ('article'))
GROUP BY node_field_data.nid, node__field_release_date_field_release_date_value, node_field_data_created
ORDER BY node__field_release_date_field_release_date_value DESC, node_field_data_created ASC
Is it possible to get this type of result set with Drupal 8 views? If so, what settings do I need? Is there a module or extension I need to employ?
Edit User prkos suggested using an exposed filter, perhaps with the better_exposed_filter
module. I've since gone down this alley, and it doesn't seem to meet the requirements. The basic problem is that, since views only looks at the entire date value, I can't specify a year to filter on at all (the interface and options for exposed filters is completely different from contextual filters). It also seems to run in to the problem that it can't auto-populate filter widgets with unique years, which is the issue I'm asking about in this question.
When I add an exposed filter, a "Single filter" type only allows entire dates, or relative dates:
When I hard-coded a value (2015) to test, as in the screenshot above, the view returned no results. This is because the filter is turning the year into a particular date in the query:
AND ((DATE_FORMAT(node__field_release_date.field_release_date_value, '%Y-%m-%d') = DATE_FORMAT('2019-05-07T20:15:00', '%Y-%m-%d')))
When I look at Group Filters, there seem to be two issues: 1. groupings must be manually specified, which is the sort of maintenance I'm looking to avoid, and 2. it still only accepts an entire date, and can't handle a year specification.
I also installed better_exposed_filters
, but it doesn't seem to provide any of the features I'm looking for.
Edit 2 Following the instructions in the first half of prkos' answer, I was able to get a list of unique year values:
But, I don't see how to use it as a filtering widget for end-users. The results are links, but they each only link to the /press-releases
URL. Because I'm getting the contextual filter value from a query parameter, I need the links to look like /press-release?year=2014
. But, because they are summary results from the contextual filter, and not fields, I can't re-write them.
So I guess this technically answers my question of how to get a view of unique years, but it doesn't give me something that I can work into a usable UI widget. I'm going to accept this answer, and ask about how to create the useable widget in another question.
Edit 3
As per prkos' suggestion, I looked at the summary results on the page, instead of just the view preview (I was pretty sure I had done this earlier, but of course you should always double-check your work).
I found that the links were not automatically populated with the value of the filter.
Here my mouse is hovering over the '2014' in FF. The screenshot doesn't capture the mouse cursor icon, but you can see which link is being hovered over, because its styled as a darker magenta color than the others:
Another test in Chrome, hovering over '2017':
So in the tests above, I was testing the summary view in the header of the press releases block. To make sure this wasn't a problem with a view-within-view, or anything, I copied the summary block display as a page. The page showed the same behavior:
Each of the above views have the same Base Path value, /press-releases
. When I tried removing the Base Path value, then there were no results, summarized or other, as prkos warned.
I don't know why the summary links on the page display were going to /year-filter-test
-- that's the path of that page display.
Summary
option on your Contextual filterWhen the filter value is NOT available
. This will give you a list of links of all the years for your users to click through (don't forget to enter your path into those options).