Skip to main content
Submitted by clemabiz on Sun, 09/17/2017 - 10:27

I need to select 'make' eg Toyota from a taxonomy list of car brands so the next taxonomy list only shows Toyota models only. I have taxonomy list "make" with Toyota, BMW, Benz etc then other lists of all the models EG "Benz" with A-Class, C-Class, ML etc for all the models. I'm using the internet example "http://www.drupal8.ovh/sites/drupal/files/2016-10/vehicle_full_wviews.zip" to add this fuctionality on to the "VehicleForm". 
Here is my code:
<?php
namespace Drupal\vehicle\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\CssCommand;
/**
 * VehicleForm.
 */
class VehicleForm extends ContentEntityForm {
//  class VehicleForm extends FormBase {
  /**
   * The term Storage.
   *
   * @var \Drupal\taxonomy\TermStorageInterface
   */
  protected $termStorage;

  /**
   * {@inheritdoc}
   */
  public function __construct(EntityTypeManagerInterface $entity) {
    $this->termStorage = $entity->getStorage('taxonomy_term');
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    // Instantiates this form class.
    return new static(
    // Load the service required to construct this class.
    $container->get('entity_type.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'vehicle_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) 
  {
    /* @var $entity \Drupal\vehicle\Entity\Vehicle */
    $form = parent::buildForm($form, $form_state);
    $entity = $this->entity;

    $terms = $this->termStorage->loadTree('make', 0, NULL, TRUE);
    $options = [];
    if ($terms) {
      foreach ($terms as $term) {
        $options[$term->getName()] = $term->getName();
      }
    }


    $form['make'] = array(
      '#type'    => 'select',
      '#title'   => $this->t('Make'),
      '#description' => 'Please enter Make of vehicle',
//      '#default_value' => $default_make,
      '#options' => $options,
      '#ajax'    => array(
        'callback' => [$this, 'selectModelsAjax'],
        'wrapper'  => 'model_wrapper',
        ),
//      '#validated' => TRUE,

    );

    $form['model'] = array(
      '#type'      => 'select',
      '#title'     => $this->t('Model'),
      '#description' => 'Please enter model of vehicle',
//      '#default_value' => $default_model,
      '#options'   => ['_none' => $this->t('- Select a Make first -')],
      '#prefix'    => '<div id="model_wrapper">',
      '#suffix'    => '</div>',
//      '#validated' => TRUE,
    );

    return $form;
}

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
  parent::save($form, $form_state);

    $entity = $this->getEntity();
    $entity_type = $entity->getEntityType();

    $arguments = [
    '@entity_type' => $entity_type->getLowercaseLabel(),
    '%entity' => $entity->label(),
    'link' => $entity->toLink($this->t('View'), 'canonical')->toString(),
    ];

    $this->logger($entity->getEntityTypeId())->notice('The @entity_type %entity has been saved.', $arguments);
    drupal_set_message($this->t('The @entity_type %entity has been saved.', $arguments));

    $form_state->setRedirectUrl($entity->toUrl('canonical'));
  }   

  /**
   * Called via Ajax to populate the Model field according brand.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @return array
   *   The form model field structure.
   */
  public function selectModelsAjax(array &$form, FormStateInterface $form_state) {
    $options = [];

    $vocabulary = 'benz';
    switch ($form_state->getValue('make')) {
      case 'Benz':
        $vocabulary = 'benz';
        break;
      case 'BMW':
        $vocabulary = 'bmw';
        break;
      case 'Toyota':
        $vocabulary = 'toyota';
        break;
    }

    $models = $this->termStorage->loadTree($vocabulary, 0, NULL, TRUE);
    if ($models) {
      foreach ($models as $model) {
        $options[$model->id()] = $model->getName();
      }
    }

    $form['model']['#options'] = $options;

//    $form_state['rebuild'] = true; // rebuild the form. not sure if this is required now.    

    return $form['model'];
  }

}   

I've been trying several things and there might be redundant code. 
Please help, I just can't get this to work

Forums