1

I have a view with two exposed filters and I want to make the second filter dependant on the first in 2 ways

  1. A user has to select an option from the first filter before the second is available to use. Achieved using Views Dependant Filters
  2. The options within the second filter are dynamically updated so only combinations that will return results are presented. Achieved following this Views AJAX Dynamic Dependent Exposed Filters tutorial and creating a custom module.

I have an example of this view available on this development server.

Select an option from filter one and the second filter becomes available and it's options are updated as expected.

The problem occurs when you select a second different option from the first filter. The AJAX does not fire and the second filter options are not updated.

Code for updating filter two with AJAX is below, but I believe the problem lies on the client side.

I appreciate your suggestions.

function dependant_keyword_filter_form_views_exposed_form_alter(&$form, &$form_state){
    if ($form['#id'] == 'views-exposed-form-annotated-bibliography-page') {

        $form['#after_build'][] = '_sort_alphabetically';

        if(!empty($form_state['values'])) {
            $form_state['input'] = array_merge($form_state['input'], $form_state['values']);
        }

        $selectedCommodity = $form_state['input']['field_commodity_tid'];
        $form['field_keywords_tid']['#options'] = _get_associative_array_from_view(
            'annotated_bibliography_dependant_keywords', // view id
            'default', // view display id
            'taxonomy_term_data_field_data_field_keywords_tid', // key field id
            'taxonomy_term_data_field_data_field_keywords_name',
            $selectedCommodity // term id of the selected shape
            );
        $form['field_commodity_tid']['#ajax'] = array(
            'callback' => '_update_keywords_callback',
            'wrapper' => 'keywords_wrapper',
            );
        $form['field_commodity_tid']['#ajax']['progress']['type'] = 'throbber';
        $form['field_commodity_tid']['#ajax']['progress']['message'] = 'Updating keywords';
        $form['field_keywords_tid']['#prefix'] = '<div id="keywords_wrapper">';
        $form['field_keywords_tid']['#suffix'] = '</div>';
    }
}

function _sort_alphabetically($form, $form_state) {
        foreach ($form_state['view']->filter as $field => $filter) {
            if ($filter->options['exposed']  && $filter->options['id'] == 'field_keywords_tid' ) {
                $field_id = $form['#info']["filter-field_keywords_tid"]['value'];
                asort($form[$field_id]['#options']);
            }
        }
        return $form;
}

function _update_keywords_callback($form, $form_state) {
    return $form['field_keywords_tid'];
}

function _get_associative_array_from_view($viewID, $viewDisplayID, $keyFieldID, $valueFieldID, $contextualFilter){
    $associativeArray = array();
    $associativeArray['All'] = t('- Any -');
    $viewResults = views_get_view_result($viewID, $viewDisplayID, $contextualFilter);
    foreach($viewResults as $viewRow) {
        $associativeArray[$viewRow->$keyFieldID] = $viewRow->$valueFieldID;
    }
    return $associativeArray;
}
1

I was able to make the second filter dependant in both ways without the need for Views Dependant Filters by adding additional logic to my hook_form_views_exposed_form_alter.

if($form_state['input']['field_commodity_tid'] === 'All')
    $form['field_keywords_tid']['#disabled'] = 1;
}

Here is the entire working code:

function dependant_keyword_filter_form_views_exposed_form_alter(&$form, &$form_state){
    if ($form['#id'] == 'views-exposed-form-annotated-bibliography-page') {

        $form['#after_build'][] = '_sort_alphabetically';

        if(!empty($form_state['values'])) {
            $form_state['input'] = array_merge($form_state['input'], $form_state['values']);
        }

        $selectedCommodity = $form_state['input']['field_commodity_tid'];
        $form['field_keywords_tid']['#options'] = _get_associative_array_from_view(
            'annotated_bibliography_dependant_keywords', // view id
            'default', // view display id
            'taxonomy_term_data_field_data_field_keywords_tid', // key field id
            'taxonomy_term_data_field_data_field_keywords_name',
            $selectedCommodity // term id of the selected shape
            );
        $form['field_commodity_tid']['#ajax'] = array(
            'callback' => '_update_keywords_callback',
            'wrapper' => 'keywords_wrapper',
            );
        $form['field_commodity_tid']['#ajax']['progress']['type'] = 'throbber';
        $form['field_commodity_tid']['#ajax']['progress']['message'] = 'Updating keywords';
        $form['field_keywords_tid']['#prefix'] = '<div id="keywords_wrapper">';
        $form['field_keywords_tid']['#suffix'] = '</div>';

        if($form_state['input']['field_commodity_tid'] === 'All')
            $form['field_keywords_tid']['#disabled'] = 1;
        }
}

function _sort_alphabetically($form, $form_state) {
        foreach ($form_state['view']->filter as $field => $filter) {
            if ($filter->options['exposed']  && $filter->options['id'] == 'field_keywords_tid' ) {
                $field_id = $form['#info']["filter-field_keywords_tid"]['value'];
                asort($form[$field_id]['#options']);
            }
        }
        return $form;
}

function _update_keywords_callback($form, $form_state) {
    return $form['field_keywords_tid'];
}

function _get_associative_array_from_view($viewID, $viewDisplayID, $keyFieldID, $valueFieldID, $contextualFilter){
    $associativeArray = array();
    $associativeArray['All'] = t('- Any -');
    $viewResults = views_get_view_result($viewID, $viewDisplayID, $contextualFilter);
    foreach($viewResults as $viewRow) {
        $associativeArray[$viewRow->$keyFieldID] = $viewRow->$valueFieldID;
    }
    return $associativeArray;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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