- πΊπΈUnited States loopy1492
This isn't really just an exposed filter issue.
For example, after years of a site running:
- I add a checkbox to a content type.
- I want any content with the checkbox checked to not be visible in a view.
- I add a filter to the view for "Not equal to true"
- The view displays no results because the values of all the existing content are "null".I would expect, instead, all the previous content to show up because they are not set to true.
- πΊπΈUnited States maskedjellybean Portland, OR
This seems like it should be part of core. The only way to do achieve the same filtered result via core right now is to expose the operation filter. Then the user has to choose "Is empty (NULL)" from a separate filter and "- Any -" from the main filter. This is not good UX.
In the meanwhile I was able to do this for a one off situation using a couple hooks and I wanted to share.
The idea is to expose the operation filter and then hide it in a form alter. Also in the form alter, add a "None" option to the main filter. Then in a query alter, if None was selected, apply a JOIN and WHERE as though "Is empty (NULL)" were chosen from the operator filter.
Things to know about the code example:
- My field is a taxonomy reference field with the machine name field_prof_languages.
- My view has the machine name profile_language_report.
- field_prof_languages_target_id_op refers to the operation filter.
- For what it's worth, you can't do this via an event subscriber because of this: https://www.drupal.org/project/hook_event_dispatcher/issues/3365175 π VIEWS_QUERY_ALTER doesn't allow unset() but equivalent hook does Active/** * Implements hook_form_FORM_ID_alter(). * * PURPOSE: Add custom "None" option to Profile Language Report view filter. */ function mymodule_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id) { if ($form['#id'] === 'views-exposed-form-profile-language-report-page-1' || $form['#id'] === 'views-exposed-form-profile-language-report-data-export-1' ) { // Hide operations field. // We instead add "None" as option to main field // and alter the query in views query alter. $form['language_wrapper']['field_prof_languages_target_id_op']['#access'] = FALSE; $options = $form['language_wrapper']['language']['#options']; $form['language_wrapper']['language']['#options'] = array_slice( $options, 0, 1, TRUE) + [ 'None' => new TranslatableMarkup( '- None (no language set) -'), ] + array_slice($options, 1, count($options) - 1, TRUE); } } /** * Implements hook_views_query_alter(). * * PURPOSE: Alter Profile Language Report view query based on * "None" option added in mymodule_form_views_exposed_form_alter. */ function mymodule_views_query_alter(ViewExecutable $view, QueryPluginBase $query) { if (isset($view->getExposedInput()['language']) && $view->getExposedInput()['language'] === 'None') { $definition = [ 'table' => 'node__field_prof_languages', 'field' => 'entity_id', 'left_table' => 'node_field_data', 'left_field' => 'nid', ]; $join = \Drupal::service('plugin.manager.views.join') ->createInstance('standard', $definition); $query->addRelationship('node__field_prof_languages', $join, 'node_field_data'); $query->addWhere( 1, 'node__field_prof_languages.field_prof_languages_target_id', NULL, 'IS NULL' ); // Remove unwanted where condition created by // our custom "None" option added in form alter. unset($query->where[0]); } }
- π§πͺBelgium beerendlauwers
+1 on this. I needed a way to provide a checkbox exposed filter that indicated if an entity reference field was empty or not, and was surprised to find that this does not exist out of the box.