Возможно ли иметь текстовое поле автозаполнения в Symfony/bootstrap?

Я использую Symfony 2.4 с пакетом Braincrafted Bootstrap. Я искал способ иметь текстовое поле автозаполнения в Bootstrap, но, похоже, мне нужна внешняя библиотека для этого («Typeahead»?).

Во-первых, это определенно невозможно сделать с помощью Bootstrap? А во-вторых, есть ли какие-то рекомендуемые альтернативы, кроме Typeahead?

Спасибо


person b85411    schedule 23.04.2014    source источник


Ответы (1)


Ввод можно сделать с помощью Symfony2, хотя это может занять некоторое время. Вот пошаговый пример:

Лицо:

Поскольку все формы (или, по крайней мере, большинство) в Symfony2 отображаются на объекты, вы должны начать здесь. Одной из важных частей сущности, для которой вам нужен заголовок, является метод __toString. В этом примере у нас есть объект Address:

class Address
{
    /**
     * @ORM\Column(type="string")
     * @Assert\NotBlank(message="Please enter an address")
     */
    protected $addressstring;

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

Форма:

Теперь, когда у нас есть миленький Address, давайте добавим его в форму EventType. В методе buildForm мы добавляем наше поле адреса:

$builder->add(
    $builder->create(
        'address', 
        'text',
        ['attr' => ['class' => 'address_typeahead']]
    )
);

Обратите внимание, что тип поля — текст, а не сущность. Это дает нам преимущество текстового ввода вместо глупого выпадающего списка или флажка. Также мы добавляем атрибут class для быстрого получения поля в javascript.

Шаблон:

Создадим простой шаблон формы:

<form action="{{ path('event_add') }}" method="post" {{ form_enctype(form) }}>
    {{ form_widget(form) }}
    <input class="btn btn-primary" type="submit" value="Create Event" />
</form>

А также добавьте немного javascript ниже:

$('.address_typeahead').typeahead({
    source: function (query, process) {
        var addressobj = $(this).parent();
        return $.get('{{ path('events_address_typeahead') }}', { 'addr': query }, function (data) {
            return process(data);
        });
    }
});

Действие:

Мы почти на месте. Но typeaheadAction отсутствует. Давайте добавим его в наш выбранный контроллер:

/**
 * @Route("/address/typeahead", name="events_address_typeahead")
 * @Method("GET")
 */
public function addressTypeaheadAction(Request $request)
{
    $addresses = // get all addresses e.g. from a repository

    return new JsonResponse(
        array_map(
            function ($val) {
                return (string) $val;
            },
            $addresses
        )
    );
}

Теперь Typeahead уже должен предоставить вам несколько приятных опций в вашей форме.

Трансформатор:

Последнее, что нам нужно сделать, это добавить DataTransformer. Благодаря этому Symfony2 может преобразовать значение поля формы в другой тип (или, в нашем случае, в сущность). Итак, давайте быстро создадим AddressTransformer:

class StringToAddressTransformer implements DataTransformerInterface
{   
    /**
     * transforms the Address-Object into a String
     */
    public function transform($addrobj)
    {
        if (!$addrobj) {
            return null;
        }

        return $addrobj->__toString();
    }

    /**
     * Reverts Transformation from String to Address Object
     */
    public function reverseTransform($address)
    {

        if (null === $address) {
            return null;
        }

        // .. do anything to transform the string into an object

        return $addrobj;
    }
}

Этот трансформер действительно творит для нас волшебство! Последний шаг — добавить его в нашу форму. Измените свой метод buildForm из шага 2 следующим образом:

$builder->add(
    $builder->create(
        'address', 
        'text',
        ['attr' => ['class' => 'address_typeahead']]
    )->addModelTransformer(new StringToAddressTransformer())
);

Ааааааааааааааааааааааааааааааааа, готово!

person ferdynator    schedule 23.04.2014
comment
+1, но будьте осторожны, если у него более одного поля, ему придется использовать новый тип поля, но отлично :) - person Healkiss; 23.04.2014
comment
Да, хороший момент, чтобы иметь в виду. И благодарю вас ;) - person ferdynator; 23.04.2014
comment
Вау спасибо за подробный ответ. Я попробую это завтра, ура! Будет ли он работать с 0.10.2 twitter.github.io/typeahead.js? - person b85411; 23.04.2014
comment
Я не знаю. Я использовал bootstrap v2 one. Вы должны проверить это сами. - person ferdynator; 23.04.2014
comment
Хорошее общее объяснение. У меня есть 2 вопроса: 1) где определяется 'address_typeahead'? 2) как это сделать с несколькими адресами? Спасибо - person eddy147; 19.03.2017
comment
@ eddy147 класс address_typeahead просто используется для селектора Javascript выше. Вы имеете в виду несколько полей ввода адреса? Просто добавьте больше входных данных в конструктор форм таким же образом. Если вы хотите иметь несколько адресных полей (например, улица, город...), вы должны быть немного хитрее. Либо разделите все, и выполните все шаги, описанные выше, для всех полей по отдельности, либо сделайте какое-нибудь причудливое разделение предоставленной строки на стороне сервера. - person ferdynator; 19.03.2017