0

I am trying to build a D7 view, and I have the view correctly only showing results using a contextual filter, but I am trying to build one more filter (an exposed one), to drill down even more.

I have a list of students, each students assigned to different districts. A user is assigned to one (or multiple) districts, but should never be assigned to all (but could be). The contextual filter is checking the assigned_user field of the district using the logged in user, and that works.

I have the student and district relationship setup, and it pulls all data from both entities correctly.

Now I am trying to build an exposed filter so that the user can select which district they want to filter by, but ONLY list the districts they are assigned to. When using the 'expose filter' option on the district name, if I use 'Single Filter' it makes it a textbox instead of a select box, and if I use 'group filter', it makes a select box, but I have to manually put in each district.

I am trying to #1, get the exposed filter to be a select list, and #2 ONLY the districts the user has access to (via the assigned_user contextual filter). The views UI doesn't appear to have a way to do this, so is it possible for me to write a hook to create the filter myself?

2 Answers 2

2

If the district is a term, entity reference, or a list field value, then you should be able to do this. Otherwise, You'll need to do something more involved (and honestly, at that point, you're probably better off just restructuring that data to work with views.

As far as only exposing options that will provide valid results, I'd recommend taking a look at Views Selective Filters (https://www.drupal.org/project/views_selective_filters). Be wary though, as the views_selective_filters module does an additional query, per selective filter as the view is loaded. Not a huge problem for 1 or 2 filters. But can start to cause performance issues if you're not careful.

Edit The question as I (now) understand it: How do you change the options of a select list exposed filter based on an arbitrary value set against the currently logged in user?

First, hook into the exposed filter form and modify the district filter.

function mymodule_form_FORM_ID_alter(&$form, &$form_state) {
  $district_options = mymodule_get_district_options();

  if (!empty($district_options)) {
    $form['field_district']['#type'] = 'select';
    $form['field_district']['#options'] = $district_options;
  }
}

Next, you need to actually write mymodule_get_district_options().

function mymodule_get_district_options() {
  // Load the current user. 
  global $user;
  $account = user_load($user->uid);

  // Default to loading all districts.
  $district_ids = FALSE;

  // Get the districts value from the loaded account.
  if (!empty($account) && !empty($account->field_districts)) {
    $district_values = $account->field_districts;
    foreach ($district_values[LANGUAGE_NONE] as $delta => $value) {
      $district_ids[] = $value['target_id'];
  }

  // Load the districts set on the current user, or ALL districts if none are set.
  $districts = entity_load('district', $district_ids);

  $options = [];
  if (!empty($districts)) {
    foreach ($districts as $district) {
      $options[$district->id] = $district->title;
    }
  }

  return $options;
}

Something along those lines should work. I haven't tested this.

8
  • The 'district' is an entity reference to an eck entity called 'district' on the 'student' entity (also an eck entity). I can get the filter to show up on the page, but it only shows up as a textbox (not a select list), and it shows ALL districts, regardless of what districts the assigned user actually has access to (its not obeying the contextual filter) I have been dabling with a custom exposed filter to do it for me, but I can't get the exposed filter to target the correct field on the entity for it to do it.
    – Ex0r
    Commented Oct 1, 2019 at 16:43
  • Your views_selective_filters worked perfectly for what I was trying to do! Thank you so much.
    – Ex0r
    Commented Oct 1, 2019 at 17:38
  • After digging further into this, this doesn't appear to work as I was expecting it to. The selective filters module appears to break down if other exposed filters are used. For example if I have an exposed filter checking a yes/no value along with the selective exposed filter, and I select 'Yes' on the other exposed filter and no results are found, any districts from the 'selective filter' that have students with 'yes' not set are removed from the list. This field is to ONLY populate the available filter values for this field based on the districts the user accessing the page has access to.
    – Ex0r
    Commented Oct 2, 2019 at 15:51
  • It's been a few years since I used views_selective_filters, but according to the module page, the filters should update as you select exposed filter values. It's possible that both fields need to be selective filters? Or you may need to perform a search/reload in-between the two filters. Some custom code would probably allow you to trigger the selective filter callback when the user selects a value for the first exposed filter.
    – lukedekker
    Commented Oct 2, 2019 at 17:53
  • Hmm, if the options aren't that flexible, I may have to seek an alternative solution. With the way this project is going new filters and requirements can easily come up tomorrow and I would have to rebuild this entire view to accommodate it. There has to be some way to do what I am trying to do. On the content creation side of it, I can use a 'views generated entity reference' field to display a select list of only options that match criteria. I can't believe there's nothing on the views/exposed filter side to do the same thing.
    – Ex0r
    Commented Oct 2, 2019 at 20:50
0

I ended up achieving this. The exposed filter was defaulting to a textbox instead of a select list, so I used hook_form_alter to change it to a select list, and since I was already altering the form I used that time to use EntityFieldQuery to pull in only the 'options' available to the user (based on the assigned_user entityreference field on the district entity). In the end, it achieved exactly what I needed it to.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.