Как создать тип формы Symfony для тегов с select2 v4

Я пытаюсь обновить уже созданный тип формы (TagsType) от выбора 2 v3 до v4. Но я обнаружил проблему, заключающуюся в том, что новое select2 использует select вместо текстового поля. Следующий код прекрасно работает с v3.

class TagsType extends AbstractType
{

    /**
     * @inheritdoc
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addViewTransformer(new StringToArrayTransformer());
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $attr = isset($view->vars['attr']) ? $view->vars['attr'] : [];

        $view->vars['attr'] = array_merge($attr, ['data-toggle' => 'tags']);
    }

    /**
     * @inheritdoc
     */
    public function getParent()
    {
        return 'text';
    }

    /**
     * @inheritdoc
     */
    public function getName()
    {
        return 'tags';
    }
}

StringToArrayTransformer:

class StringToArrayTransformer implements DataTransformerInterface
{

    /**
     * @inheritdoc
     */
    public function transform($value)
    {
        if (!$value ) {
            return [];
        }

        if (!is_array($value)) {
            throw new TransformationFailedException('Expected a Array.');
        }

        return implode(',', $value);
    }

    /**
     * @inheritdoc
     */
    public function reverseTransform($value)
    {
        if (null === $value) {
            return [];
        }

        if (!is_string($value)) {
            throw new TransformationFailedException('Expected a String.');
        }

        return explode(',', $value);
    }
}

Приведенный выше код отлично работает с сущностью с полем типа simple_array (разделенные запятой). Мне нужно сделать то же самое, но с использованием новой версии select2.

Рефакторинг:

class TagsType extends AbstractType
{

   /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $attr = isset($view->vars['attr']) ? $view->vars['attr'] : [];

        $view->vars['attr'] = array_merge($attr, ['data-toggle' => 'tags']);
    }

    /**
     * @inheritdoc
     */
    public function getParent()
    {
        return 'choice';
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(['multiple' => true]);
    }


    /**
     * @inheritdoc
     */
    public function getName()
    {
        return 'tags';
    }
}

Рефакторинг генерирует тег select с несколькими, но пустыми. А когда попробуем добавить какую-то опцию (Tag) проверка не проходит, потому что динамическое создание новых опций в select.

Мои вопросы:

  • Как реализовать выбор с динамическими опциями в symfony?
  • Как установить выбор по умолчанию из данных поля (массива)

1 ответ

Забудьте все о ',' и преобразуйте строку в массив или наоборот и сохраните каждую сущность Tag по отдельности.

Таким образом, чтобы сделать вашу форму совместимой с select2-v4.x, вам нужно одно поле EntityType с атрибутом "множественный", установленным в значение "ИСТИНА".

Каждая вещь обрабатывается Symfony, каждая опция (и) в теге select вашей формы связана с ее сущностью.

Я только что нашел это решение, и оно работает для меня, но я не знаю, может быть, некоторые вещи отсутствуют...

Очень старый вопрос, но я нашел его из поисковой системы. Я попытался сделать это с помощью преобразователя данных simple_array + - это неправильный путь (как сказал @YaserKH). Лучше сделать теги как Entity Tag и т. Д. (Вы можете найти в официальных документах). Но если вам нужно простое решение по каким-то причинам (как я):

  1. Создать столбец типа Text в базе данных (не simple_array)
  2. Определите его как HiddenType в конструкторе форм:
    $builder->add('tagsForSearch', HiddenType::class, [ 'required' => false ])
  1. Сделайте веточку вроде:
    {{ form_row(form.tagsForSearch) }}
    <select id="tags" multiple="multiple">
        {% for tag in form.tagsForSearch.vars.value|split(',')|default %}
            <option value="{{ tag|raw }}" selected="selected">{{ tag|raw }}</option>
        {% endfor %}
    </select>
  1. И сценарий:
$('#tags').select2({
    tags: true
});
$('#form').submit(function () {
    var tags = $('#tags').select2().val().join(',');
    $('#{{ form.tags.vars.id }}').val(tags);
});
Другие вопросы по тегам