0

The Problem: I have 5 select elements in my form, all are linked to their own ajax callback. Each select element has the same wrapper because the whole container should be updated when any of the select boxes change. Only the first ajax call works, after that it throws:

The specified #ajax callback is empty or not callable.

In additon to the buildForm and ajax callbacks below, I have another function called "ajaxMatrixStepChange" which changes the #access property of the desired elements based on the callback invoked.

I can't figure out why all but the first ajax callback is empty or not callable.

buildForm:


//content container for matrix
$form['details']['container'] = ['#type' => 'container'];
$form['details']['container']['#attributes']['id'] = 'application_matrix'; 
$form['details']['container']['#attributes']['style'] = 'display: flex;';

//build select options for vehicle years
$form['details']['container']['year'] = [
    '#type' => 'select',
    '#title' => t('Year:'),
    '#empty_option' => t('--Select Year--'),
    '#access' => TRUE,
    '#options' => count($application_matrix['years']) ? $application_matrix['years'] : [],
    '#attributes' => [
        'style' => 'margin-right: 15px;'
    ],
    '#ajax' => [
        'wrapper' => 'application_matrix',
        'callback' => [$this, 'ajaxMatrixYear_Changed']
    ]
];

//build select options for vehicle makes
$form['details']['container']['make'] = [
    '#type' => 'select',
    '#title' => t('Make:'),
    '#empty_option' => t('--Select Make--'),
    '#access' => FALSE,
    '#options' => count($application_matrix['makes']) ? $application_matrix['makes'] : [],
    '#attributes' => [
        'style' => 'margin-right: 15px;'
    ],
    '#ajax' => [
        'wrapper' => 'application_matrix',
        'callback' => [$this, 'ajaxMatrixMake_Changed']
    ]
];

//build select options for vehicle models
$form['details']['container']['model'] = [
    '#type' => 'select',
    '#title' => t('Model:'),
    '#empty_option' => t('--Select Model--'),
    '#access' => FALSE,
    '#options' => count($application_matrix['models']) ? $application_matrix['models'] : [],
    '#attributes' => [
        'style' => 'margin-right: 15px;'
    ],
    '#ajax' => [
        'wrapper' => 'application_matrix',
        'callback' => [$this, 'ajaxMatrixModel_Changed']
    ]
];

//build select options for vehicle series
$form['details']['container']['series'] = [
    '#type' => 'select',
    '#title' => t('Series:'),
    '#empty_option' => t('--Select Series--'),
    '#access' => FALSE,
    '#options' => count($application_matrix['series']) ? $application_matrix['series'] : [],
    '#attributes' => [
        'style' => 'margin-right: 15px;'
    ],
    '#ajax' => [
        'wrapper' => 'application_matrix',
        'callback' => [$this, 'ajaxMatrixSeries_Changed']
    ]
];

//build select options for vehicle engine
$form['details']['container']['engine'] = [
    '#type' => 'select',
    '#title' => t('Engine:'),
    '#empty_option' => t('--Select Engine--'),
    '#access' => FALSE,
    '#options' => count($application_matrix['engines']) ? $application_matrix['engines'] : [],
    '#attributes' => [
        'style' => 'margin-right: 15px;'
    ],
    '#ajax' => [
        'wrapper' => 'application_matrix',
        'callback' => [$this, 'ajaxMatrixEngine_Changed']
    ]
];

AJAX Callbacks:


public function ajaxMatrixYear_Changed(array &$form, FormStateInterface $form_state)
{
    $this->ajaxMatrixStepChange($form, 1);
    return $form['details']['container'];
}

public function ajaxMatrixMake_Changed(array &$form, FormStateInterface $form_state)
{
    $this->ajaxMatrixStepChange($form, 2);
    return $form['details']['container'];
}

public function ajaxMatrixModel_Changed(array &$form, FormStateInterface $form_state)
{
    $this->ajaxMatrixStepChange($form, 3);
    return $form['details']['container'];
}

public function ajaxMatrixSeries_Changed(array &$form, FormStateInterface $form_state)
{
    $this->ajaxMatrixStepChange($form, 4);
    return $form['details']['container'];
}

public function ajaxMatrixEngine_Changed(array &$form, FormStateInterface $form_state)
{
    $this->ajaxMatrixStepChange($form, 5);
    return $form['details']['container'];
}
  • The most important rule for Ajax callbacks, never change $form. See Examples for Developers. You'll find two examples for dependent dropdowns, one in the Ajax submodule and a more simple one in the Form API submodule. – 4k4 Jan 22 at 10:37

Your Answer

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

Browse other questions tagged or ask your own question.