Включить Select2Search в форме Symfony

Я хочу включить поиск select 2 в моей форме Symfony, что я пробовал до сих пор:

В моем классе формы у меня есть это:

->add('parent', EntityType::class, [
                'class' => Category::class,
                'choice_label' => 'title',
                'attr' => [
                    'class' => 'select2'
                ]
            ])

В моем файле ветки это:

<head>
    <link href = "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.2-rc.1/css/select2.min.css" rel = "stylesheet" />
    <!-- Loading jquery here--><script src = "https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    <script src = "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.2-rc.1/js/select2.min.js"></script>
</head>

    {{ form_start(form) }}
    <script type = "text/javascript">
        $('select').select2();
    </script>
    {{ form_widget(form) }}
    {{ form_end(form) }}

Но у меня нет раскрывающегося списка с панелью поиска. Просто выпадающее меню Symfony по умолчанию. Что я делаю неправильно

Это точное содержание вашего шаблона или вы просто разместили соответствующие части?

Philippe-B- 19.05.2018 03:58

@ Philippe-B - точное содержимое файла ветки

Noob 19.05.2018 11:31

Я обновил свой ответ образцом кода.

Philippe-B- 19.05.2018 15:02

вы уже решили проблему?

Juan I. Morales Pestana 28.05.2018 22:20

@ JuanI.MoralesPestana Нет, возникают ошибки, если я загружаю несколько jQuery

Noob 29.05.2018 00:25

@Noob, пожалуйста, обновите свой вопрос, указав все параметры и ошибки, чтобы я мог вам помочь. Для меня он работает отлично. Пожалуйста, обновите свой вопрос с помощью Entity, формы, преобразователя данных, если он у вас есть, и представления, а также добавьте ошибки

Juan I. Morales Pestana 29.05.2018 00:45

ты проверил мой последний ответ? то же самое для множественного выбора. вам нужно только установить опцию multiple true в форме и закодировать, чтобы предоставить правильную информацию о сопоставлении

Juan I. Morales Pestana 31.05.2018 20:39
JS - События опций формы
JS - События опций формы
В продолжение предыдущей статьи CSS - стили, связанные с вводом формы , в этой статье мы будем использовать JS для взаимодействия с формами, на этот...
CSS - Стили, связанные с вводом формы
CSS - Стили, связанные с вводом формы
Общими стилями ввода для форм являются Input (включая Text, Radio, checkbox), Select и Textarea, из которых Input относительно прост, поэтому в этой...
Создание многостраничной формы заявления о приеме на работу с помощью Angular
Создание многостраничной формы заявления о приеме на работу с помощью Angular
Наличие на корпоративном сайте форм заявлений о приеме на работу, или "трудовых анкет", экономит время и деньги как для соискателей, так и для...
5
7
1 514
4

Ответы 4

Основная причина в том, что поле создается после того, как вы пытаетесь настроить его таргетинг, с помощью этой строки:

{{ form_widget(form) }}

После этого должен быть выполнен JavaScript, чтобы можно было настроить таргетинг на это поле (кроме того, HTML-структура вашего шаблона неверна).

Попробуй это :

<!DOCTYPE html>
<html>
<head>
    <title>Test form</title>
    <link href = "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.2-rc.1/css/select2.min.css" rel = "stylesheet" />
    <!-- Loading jquery here--><script src = "https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    <script src = "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.2-rc.1/js/select2.min.js"></script>
</head>
<body>
    {{ form_start(form) }}
    {{ form_widget(form) }}
    {{ form_end(form) }}

    <script>
        $('select').select2();
    </script>
</body>
</html>

Обычно лучше дождаться загрузки страницы перед выполнением скриптов, используя jQuery, вы можете убедиться, что это так, изменив скрипт на это:

<script>
    $(document).ready(function(){
        $('.select2').select2();
    });
</script>

Обратите внимание, что я также изменил селектор jQuery, чтобы использовать класс, который вы добавили в поле в построителе форм. Таким образом вы управляете выбранным полем, на которое хотите настроить таргетинг.

Для этого есть хорошая связка: ТетранцБандл

Вы можете настроить поле формы в классе FormType следующим образом:

            ->add('product', Select2EntityType::class, [
                'label'=>'product',
                'required'=>true,
                'mapped'=>true,
                'multiple' => false,
                'remote_route' => 'product_select2_ajax',
                'class' => 'AppBundle:Product',
//                'property' => 'name',
                'minimum_input_length' => 0,
                'page_limit' => 10,
                'allow_clear' => true,
                'delay' => 250,
                'cache' => true,
                'cache_timeout' => 60000, // if 'cache' is true
                'language' => 'pl',
                'placeholder' => "select.product",
            ])

Вы запускаете компоненты select2 без конфигурации, поэтому он не знает, где находится источник данных.

Перед тем, как приступить к кодированию, необходимо установить и настроить FOSJsRoutingBundle. Этот пакет поможет вам получить доступ к маршрутам ajax.

Для полностью настроенной синхронизации symfony-forms ~ select2 вы можете сделать что-то вроде этого.

Entity Person

class Person
{
    /**
     * @var integer
     *
     * @ORM\Column(name = "id", type = "integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy = "SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName = "person_id_seq", allocationSize=1, initialValue=1)
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name = "name", type = "string", nullable=true)
     */
    private $name;

    /**
     * @var Country
     *
     * @ORM\ManyToOne(targetEntity = "Country")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name = "country_id", referencedColumnName = "id")
     * })
     */
    private $country;



    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Person
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set country
     *
     * @param \AppBundle\Entity\Country $country
     *
     * @return Person
     */
    public function setCountry(\AppBundle\Entity\Country $country = null)
    {
        $this->country = $country;

        return $this;
    }

    /**
     * Get country
     *
     * @return \AppBundle\Entity\Country
     */
    public function getCountry()
    {
        return $this->country;
    }

    public function __toString()
    {
        return $this->name;
    }
}

Entity Country

class Country
{
    /**
     * @var integer
     *
     * @ORM\Column(name = "id", type = "integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy = "SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName = "country_id_seq", allocationSize=1, initialValue=1)
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name = "name", type = "string", nullable=true)
     */
    private $name;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Country
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    public function __toString()
    {
        return $this->name;
    }
}

Country repository

класс CountryRepository расширяет \ Doctrine \ ORM \ EntityRepository {

 public function countriesSelect2($term)
    {
        $qb = $this->createQueryBuilder('c');

        $qb->where(
            $qb->expr()->like($qb->expr()->lower('c.name'), ':term')
        )
            ->setParameter('term', '%' . strtolower($term) . '%');

        return $qb->getQuery()->getArrayResult();
    }
}

Country controller

Проверьте, как маршрут предоставляется параметру options и возвращает JsonResponse. Вы также можете использовать сериализатор.

/**
 * Country controller.
 *
 * @Route("countries")
 */
class CountryController extends Controller
{
    /**
     * Lists all person entities.
     *
     * @Route("/", name = "countries",options = {"expose"=true})
     * @Method("GET")
     */
    public function indexAction(Request $request)
    {
        $countryRepo = $this->getDoctrine()->getRepository('AppBundle:Country');
        $data = $countryRepo->countriesSelect2($request->get('q', ''));

        //$response = $this->get('serializer')->serialize($data,'json');

        return new JsonResponse($data);
    }
}

Пока все хорошо, теперь переходим к хорошим деталям, давайте настроим нашу форму

PersonType

class PersonType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name')
            ->add('country',EntityType::class,[
                'class' => Country::class,
                'attr' => [
                  'class' => 'select2', // the class to use with jquery
                    'data-source' => 'countries', //the exposed route name for data-soirce as attr
                    'data-allow-clear' => 'true'//another extra attr to customize
                ],
            ]);
    }/**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Person'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_person';
    }
}

JS, showing the select2

Помните, что вы уже настроили select2 опции с атрибутами, вам просто нужно правильно их использовать

$(document).ready(function () {
            $('.select2').each(function () {//using the select2 class
                if (!$().select2) {//checking the script
                    return;
                }
                $.fn.select2.defaults.set("theme", "bootstrap");//some theming if you want

                $($(this)).select2({
                    placeholder: "Select",
                    width: 'auto',
                    allowClear: $(this).attr("data-allow-clear") ? $(this).attr("data-allow-clear") : true, //using my options from the form
                    ajax: {
                        url: Routing.generate($(this).attr("data-source")), //here its the magic
                        dataType: 'json',
                        processResults: function (data) {
                            //console.info(data);
                            return {
                                results: $.map(data, function (item) {
                                    return {
                                        text: item.name, //you need to map this because the plugin accepts only id and text
                                        id: item.id
                                    }
                                })
                            };
                        }
                    }
                });
            });
        });

после этого все готово. Весь код работает, пока я тестировал себя

Надеюсь, поможет!

Попробуй это :

<script type = "text/javascript">
    $(document).ready(function() {
    $('.select2').select2(); //instead $('select2').select2();
});
</script>

см. Как выбрать класс в JQuery и пример базового использования

Другие вопросы по теме