Let's say we have a content type named article, which has a created field by default, and we want to filter by year. To do this, we designed a view that lists all article contents.
I will use this module to add views filter by year exact, instead of full date like mm-dd-yyyy you can use date year like yyyy.
Then I will add Authored on field to Filter criteria like this:
Then I change my field to become select field not textfield with this code:
/**
* Implements hook_form_FORM_ID_alter().
*/
function mytheme_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id)
{
if (isset($form['#id']) && $form['#id'] == 'views-exposed-form-news-page-1') {
$options = &drupal_static(__FUNCTION__);
if (is_null($options)) {
$cid = 'node:article:year';
$data = \Drupal::cache()->get($cid);
if (!$data) {
$options = [];
$options[''] = t('- All -');
$query = \Drupal::entityQuery('node');
$query->condition('type', 'article')
->condition('status', 1)
->sort('created', 'ASC');
$result = $query->execute();
if ($result) {
$nodes = Node::loadMultiple($result);
foreach ($nodes as $node) {
$date = $node->created->value;
$date = date('Y-m-d H:i:s', $date);
if ($date) {
$date = new DrupalDateTime($date, new DateTimeZone('UTC'));
$year = $date->format('Y');
if (!isset($options[$year])) {
$options[$year] = $year;
}
}
}
}
$cache_tags = ['node:article:year'];
\Drupal::cache()->set($cid, $options, CacheBackendInterface::CACHE_PERMANENT, $cache_tags);
} else {
$options = $data->data;
}
}
// change your field type and options here
$form['year'] = [
'#type' => 'select',
'#options' => $options,
];
}
}