1

I want the user to make select the car that he owns. So i am creating a custom field with multiple selects (brand, model, fuel supply, cubic capacity and horse pover).

As i select the brand, no problem showing the models, but as soon as i select the model, the callback is not called.

<?php
/**
 * @file
 * Contains \Drupal\test\Plugin\Field\FieldWidget\UsatoWidget.
 */

namespace Drupal\test\Plugin\Field\FieldWidget;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ChangedCommand;
use Drupal\Core\Ajax\CssCommand;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\InvokeCommand;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Field\WidgetBase;

/**
 * Plugin implementation of the 'social' widget.
 *
 * @FieldWidget (
 *   id = "usatoWidget",
 *   label = @Translation("Usato widget"),
 *   field_types = {
 *     "usato"
 *   }
 * )
 */
class UsatoWidget extends WidgetBase {
  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $marche=$modelli=$alimentazioni=array();
    $terms = \Drupal::entityManager()->getStorage('taxonomy_term')->loadTree('marche');
    foreach($terms as $term)
        $marche[$term->tid]=$term->name;


    $terms = \Drupal::entityManager()->getStorage('taxonomy_term')->loadTree('alimentazioni');
    foreach($terms as $term)
        $alimentazioni[$term->tid]=$term->name;

    $element['usato_marca'] = array(
      '#type' => 'select',
      '#title' => $this->t('Marca'),
      '#options' => $marche,
      '#prefix' => '<div id="usato_marche_ajax">',
     '#suffix' => '</div>',
      '#ajax' => array(
        'callback' => 'Drupal\test\Plugin\Field\FieldWidget\UsatoWidget::ajaxHandlerMarca',
        #'callback' => [$this, 'ajaxHandlerMarca'],
        'wrapper' => 'usato_modelli_ajax',
        'event' => 'change',
        'method' => 'html',
        'progress' => array(
            'type' => 'throbber',
            'message' => 'Caricamento modelli',
        )
    )
    );

    $element['usato_modello'] = array(
      '#type' => 'select',
      '#title' => 'Modello',
      #'#options' => $modelli,
      '#prefix' => '<div id="usato_modelli_ajax">',
      '#suffix' => '</div>',
      '#ajax' => array(
        #'callback' => [$this, 'ajaxHandlerModello'],
        'callback' => 'Drupal\test\Plugin\Field\FieldWidget\UsatoWidget::ajaxHandlerModello',
        'wrapper' => 'usato_alimentazione_ajax',
        'event' => 'change',
        'method' => 'html',
        'progress' => array(
            'type' => 'throbber',
            'message' => 'Caricamento alimentazioni',
        )
        )
    );

    $element['usato_alimentazione'] = array(
      '#type' => 'select',
      '#title' => 'Alimentazione',
      #'#options' => $alimentazioni,
      '#prefix' => '<div id="usato_alimentazione_ajax">',
      '#suffix' => '</div>',
    );


    $element += [
      '#type' => 'fieldset',
    ];

    return array('value' => $element);
  }
public function ajaxHandlerModello(array &$form, FormStateInterface $form_state) {
        $ajax_response = new AjaxResponse();
        $output=array();
        $triggering_element = $form_state->getTriggeringElement();

        $query = \Drupal::entityQuery('node');
        $query->condition('status', 1);
        $query->condition('type', 'auto');
        $query->condition('field_modello',$triggering_element['#value']);
        $count_budget = $query->execute();

        $nodi=node_load_multiple($count_budget);
        foreach($nodi as $id=>$result){
            $term = taxonomy_term_load($result->get('field_alimentazione')->getString());
            if($term)
                if(!in_array($term->getName(),$output))
                $output[$id]=$term->getName();
        }

        $form['usato_alimentazione'] = array(
          '#type' => 'select',
          '#title' => $this->t('Alimentazione'),
          '#options' => $output,
          '#prefix' => '<div id="usato_alimentazione_ajax">',
          '#suffix' => '</div>',
        );

        $ajax_response->addCommand(new HtmlCommand('#usato_alimentazione_ajax', $form['usato_alimentazione']));
        return $ajax_response;
    }

  public function ajaxHandlerMarca(array &$form, FormStateInterface $form_state) {
        $ajax_response = new AjaxResponse();
        $output=array();
        $triggering_element = $form_state->getTriggeringElement();

        $query = \Drupal::entityQuery('node');
        $query->condition('status', 1);
        $query->condition('type', 'auto');
        $query->condition('field_marca',$triggering_element['#value']);
        $count_budget = $query->execute();

        $nodi=node_load_multiple($count_budget);
        foreach($nodi as $id=>$result){
            $term = taxonomy_term_load($result->get('field_modello')->getString());
            if($term)
                if(!in_array($term->getName(),$output))
                $output[$id]=$term->getName();
        }

        $form['usato_modello'] = array(
          '#type' => 'select',
          '#title' => 'Modello',
          '#options' => $output,
          #'#prefix' => '<div id="usato_modelli_ajax">',
         #'#suffix' => '</div>'
         '#ajax' => array(
        #'callback' => [$this, 'ajaxHandlerModello'],
        'callback' => 'Drupal\test\Plugin\Field\FieldWidget\UsatoWidget::ajaxHandlerModello',
        'wrapper' => 'usato_alimentazione_ajax',
        'event' => 'change',
        'method' => 'html',
        'progress' => array(
            'type' => 'throbber',
            'message' => 'Caricamento alimentazioni',
        )
        )
        );

        $ajax_response->addCommand(new HtmlCommand('#usato_modelli_ajax', $form['usato_modello']));
        return $ajax_response;
    }
}

I am sending an email inside the ajaxHandlerModello function so I know for sure that is not triggered, how can't it work?

1 Answer 1

2

You're creating form elements in your ajax callback. You cannot do this, as the form has already been cached before this point, and the settings generated. You need to create any form elements inside the formElement() method. You can determine if the form has been submitted by checking values in the $form_state - no values for your elements will exist on the initial form build, and will exist in ajax callbacks.

Your Answer

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

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