分类列表依赖于另一个分类列表中的选择,drupal 8

时间:2017-08-20 18:11:39

标签: forms entity taxonomy drupal-8

我有一个分类选项列表 make ,我选择说丰田

  1. 我想要第二个分类选项列表只包含丰田模型(例如Corolla,hilux等......)。
  2. 当我选择Benz时,第二个列表将包含C-Class,ML等......
  3. 我已经通过xampp localhost,windows 10上的google示例创建了实体工具。

    在我的车辆表格中,我可以填充第一个列表。但第二个似乎是空的。

    这是我的代码。请帮忙:

    public function buildForm(array $form, FormStateInterface $form_state, $params = NULL) {
      $options = array(); 
      $tax = "make";  
      $terms = \Drupal::entityManager()->getStorage('taxonomy_term')->loadTree($tax, $parent = 0, $max_depth = NULL, $load_entities = FALSE);
      foreach ($terms as $term) {
        $options[] = $term->name;
      } 
    
      $form['make'] = array(
        '#type' => 'select',
        '#title' => t('Make'),
        'weight' => 0,
        '#options' => $options,
        '#ajax' => array(
          'callback' => [$this, 'changeOptionsAjax'],
          'wrapper' => 'model_wrapper',
        ),
      );
    
      $form['model'] = array(
        '#type' => 'select',
        '#title' => t('Model'),
        'weight' => 1,
        '#options' => $this->getOptions($form_state),
        '#prefix' => '<div id="model_wrapper">',
        '#suffix' => '</div>',
      );
    
      return $form;
    }
    
    public function getOptions(FormStateInterface $form_state) {
      $options = array();
      if ($form_state->getValue('make') == "Benz") { 
        $tax="benz";
      }
      elseif ($form_state->getValue('make') == "BMW") {
        $tax="bmw";
      } 
      elseif ($form_state->getValue('make') == "Toyota") {
        $tax="toyota";
      } 
      else {
        $tax="title";
        // title is just another taxonomy list I'm using as default if make is not found
      }
    
      $terms = \Drupal::entityManager()->getStorage('taxonomy_term')->loadTree($tax, $parent = 0, $max_depth = NULL, $load_entities = FALSE);
      foreach ($terms as $term) {
        $options[] = $term->name;
      }  
      return $options;
    }
    
    public function changeOptionsAjax(array &$form, FormStateInterface $form_state) {
      return $form['model'];
    }
    

1 个答案:

答案 0 :(得分:3)

在这里,我根据您的示例VehiculesForm.php

为您提供了一份工作示例

我冒昧地重命名一些变量以提高可读性。

<?php

namespace Drupal\example\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;

/**
 * VehiculesForm.
 */
class VehiculesForm 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 'vehicules_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $params = NULL) {
    $brands = $this->termStorage->loadTree('make', 0, NULL, TRUE);
    $options = [];
    if ($brands) {
      foreach ($brands as $brand) {
        $options[$brand->getName()] = $brand->getName();
      }
    }
    $form['brand'] = array(
      '#type'    => 'select',
      '#title'   => $this->t('brand'),
      '#options' => $options,
      '#ajax'    => array(
        'callback' => [$this, 'selectModelsAjax'],
        'wrapper'  => 'model_wrapper',
      ),
    );

    $form['model'] = array(
      '#type'      => 'select',
      '#title'     => $this->t('Model'),
      '#options'   => ['_none' => $this->t('- Select a brand before -')],
      '#prefix'    => '<div id="model_wrapper">',
      '#suffix'    => '</div>',
      '#validated' => TRUE,
    );

    $form['actions']['submit'] = [
      '#type'  => 'submit',
      '#value' => $this->t('Send'),
    ];

    return $form;
  }

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

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

  /**
   * 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 = 'title';
    switch ($form_state->getValue('brand')) {
      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;

    return $form['model'];
  }
}

另外,我建议你对你的代码做一些改进:

  • 请勿使用switch,而是将您的分类法与参考字段相关联。
  • 添加验证以确保安全性(例如,检查我们不会欺骗您的字段)!!
  • 请勿使用品牌名称,而应使用ID。避免$options[$brand->getName()] = $brand->getName();并使用$options[$brand->id()] = $brand->getName();
  • 之类的内容

希望它会对你有所帮助!