经常我们自定义select表单可能需要加载大量的entity. 导致性能很低下. 代码如下. 当我的term address有超过1000个时,页面就需要很久了.
$termStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
$options = [];
foreach($termStorage->loadByProperties(['vid' => 'address']) as $entity) {
$options[$entity->id()] = $entity->label();
}
$form['address'] = [
'#type' => 'select',
'#title' => $this->t('Address'),
'#options' => $options,
'#required' => TRUE,
];
这时我们可以使用select2. 使用select的ajax加载选择项, 下载并启用select2. 我们在里面定义了options来自自定义路由: #autocomplete_route_name = test_code.address_autocomplete. 我们这时只需要定义此路由返回部分数据就行. 因为select2有搜索功能. 我们不需要返回全部
<?php
namespace Drupal\test_code\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\Element\EntityAutocomplete;
/**
* Provides a test_code form.
*/
class SelectForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'test_code_select';
}
public static function AddressAutocompleteCallback(&$element) {
$complete_form = [];
$element = EntityAutocomplete::processEntityAutocomplete($element, new FormState(), $complete_form);
$element['#autocomplete_route_name'] = 'test_code.address_autocomplete';
return $element;
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['address'] = [
'#type' => 'select2',
'#select2' => [
'minimumInputLength' => 0,
],
'#autocomplete' => true,
'#target_type' => 'taxonomy_term',
'#autocomplete_route_callback' => self::class . '::AddressAutocompleteCallback',
'#autocomplete_route_parameters' => [],
'#title' => $this->t('Address'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
}
}
定义路由:
test_code.address_autocomplete:
path: '/test-code/example'
defaults:
_title: 'Example'
_controller: '\Drupal\test_code\Controller\AutocompleteAddress::build'
requirements:
_permission: 'access content'
定义controller只返回50条数据。 可以搜索相关更多的数据
<?php
namespace Drupal\test_code\Controller;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
/**
* Returns responses for test_code routes.
*/
class AutocompleteAddress extends ControllerBase {
/**
* Builds the response.
*/
public function build(Request $request) {
$keyword = $request->query->get('q');
$termStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
$query = $termStorage->getQuery();
// 这里的keyword是select2搜索的关键词.
if ($keyword) {
$query->condition('name', "%{$keyword}%", 'LIKE');
}
$query->range(0, 50);
$ids = $query->execute();
$results = [];
if ($ids) {
foreach($termStorage->loadMultiple($ids) as $entity) {
$results[] = (object)[
'id' => $entity->id(),
'text' => $entity->label()
];
}
}
return new JsonResponse([
'results' => $results
]);
}
}