3

I have made a form for my module with a button using AJAX callback to fill in values in multiple select form another multiple select but when pressing the button the AJAX not triggered at all and when checking the logs an exception shows with the message:

Symfony\Component\HttpKernel\Exception\HttpException: The specified #ajax callback is empty or not callable. in Drupal\Core\Form\FormAjaxResponseBuilder->buildResponse() (line 67

Here is my code:

public function getFormId() {
    return 'ads_admin_form';
}

public function buildForm(array $form, FormStateInterface $form_state) {

    $form['#attached']['library'][] = 'Place_Ads/general';
    $form['cats-wrapper'] = [
        '#type' => 'container',
        '#attributes' => ['id' => 'cats-wrapper', 'class' => ['shownselect']],
    ];
    $form['bind-wrapper'] = [
        '#type' => 'container',
        '#attributes' => ['id' => 'bind-wrapper', 'class' => ['shownselect']],
    ];
    $form['cats-wrapper']['cats'] = array(
        '#type' => 'select',
        '#title' => t('Category'),
        '#options' => Place_AdsController::getClassifiedContentTypes(),
        '#ajax' => array(
            'callback' => '::catSelectedCallback',
            'wrapper' => 'bind-wrapper',
            'effect' => 'fade',
            'event' => 'change',
            'progress' => array(
                'type' => 'throbber',
                'message' => NULL,
            ),
        ),
    );
    $form['bind-wrapper']['terms-wrapper'] = [
        '#type' => 'container',
        '#attributes' => ['id' => 'terms-wrapper', 'class' => ['shownselect']],
    ];
    $form['bind-wrapper']['fields-wrapper'] = [
        '#type' => 'container',
        '#attributes' => ['id' => 'fields-wrapper', 'class' => ['shownselect']],
    ];
    $form['bind-wrapper']['terms-wrapper']['terms'] = array(
        '#type' => 'select',
        '#title' => t('Available Terms'),
        '#multiple' => TRUE,
        '#options' => NULL,
        '#size' => 7,
    );
    $form['bind-wrapper']['terms-wrapper']['addTermsBtn'] = array(
        '#type' => 'button',
        '#value' => t('>>'),
        '#ajax' => array(
            'callback' => '::termsSelectedCallback',
            'wrapper' => 'selectedterms',
            'effect' => 'fade',
            'event' => 'click',
            'prevent' => 'submit',
            'progress' => array(
                'type' => 'throbber',
                'message' => NULL,
            ),
        ),
        '#attributes' => ['class' => ['bindBtn']],
    );
    $form['bind-wrapper']['terms-wrapper']['selectedterms'] = array(
        '#type' => 'select',
        '#title' => t('Selected Terms'),
        '#multiple' => TRUE,
        '#options' => NULL,
        '#size' => 7,
    );
    $form['bind-wrapper']['fields-wrapper']['fields'] = array(
        '#type' => 'select',
        '#multiple' => TRUE,
        '#title' => t('Available Fields'),
        '#options' => NULL,
        '#size' => 7,
    );
    $form['bind-wrapper']['fields-wrapper']['addFieldsBtn'] = array(
        '#type' => 'button',
        '#value' => t('>>'),
        //'#executes_submit_callback' => FALSE,
        //'#limit_validation_errors' => FALSE,
        '#attributes' => ['class' => ['bindBtn'], 'onclick' => 'return (false);'],
    );
    $form['bind-wrapper']['fields-wrapper']['selectedfields'] = array(
        '#type' => 'select',
        '#multiple' => TRUE,
        '#title' => t('Selected Fields'),
        '#options' => NULL,
        '#size' => 7,
    );

    $form['bindFields'] = array(
        '#type' => 'submit',
        '#value' => t('Save'),
        '#attributes' => ['id' => 'bindFieldsBtn'],
        '#submit' => ['::submitForm'],
    );
    return $form;
}

public function catSelectedCallback(array &$form, FormStateInterface $form_state) {
    $val = $form_state->getValue('cats');
    $terms = Place_AdsController::getsubCategory($val, 10);
    $currFields = Place_AdsController::contentTypeFields($val);
    unset($terms[current(array_keys($terms))]);
    $form['bind-wrapper']['terms-wrapper']['terms']['#options'] = $terms;
    //$form['bind-wrapper']['terms-wrapper']['#attributes']['class'] = ['shownselect'];
    $form['bind-wrapper']['fields-wrapper']['fields']['#options'] = $currFields;
    //$form['bind-wrapper']['fields-wrapper']['#attributes']['class'] = ['shownselect'];

    return $form['bind-wrapper'];
}

public function termsSelectedCallback(array &$form, FormStateInterface &$form_state) {
    $selected_index = $form_state['values']['terms']['und'];
    $val = $form_state->getValue('terms');
    $form['bind-wrapper']['terms-wrapper']['selectedterms']['#options'] = $val;
    return $form['bind-wrapper']['terms-wrapper']['selectedterms'];
}

public function submitForm(array &$form, FormStateInterface $form_state) {
    drupal_set_message('Nothing Submitted. Just an Example.');
    $new_node = array();
    foreach ($form_state->getValues() as $key => $value) {
        $new_node[$key] = $value;
    }
}
4

Not totally sure but I think that the problem is that both buttons (addTermsBtn and addFieldsBtn) have the same #value. Try to use different #value for the buttons or use #name attribute for differentiate them.

  • Wow.. its really working now with changing the value. even if the values are kept equal and given #name attribute for each one solved the problem thanks to you @marco – Emad Karhely Sep 4 '16 at 20:03
1

Change your callbacks to be like this:

'callback' => [$this, 'catSelectedCallback'],
  • not working, besides it's actually the button ajax that fire the exeption not the select ajax – Emad Karhely Sep 4 '16 at 10:14
  • Why should he? The ::methodName notation is specifically supported by Drupal just to be a shorthand to this longer form. – Gábor May 26 '18 at 11:00
  • For some reason it worked for me, and ::submitForm notation didn't. So there has to be a difference. – Łukasz Zaroda Aug 19 at 13:23

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.