Подтвердить что ты не робот

Можно ли разместить html внутри кнопки формы Symfony с Twig?

Я пытаюсь поместить html внутри кнопки формы с помощью twig like:

{{ form_widget(form.jiraStatus, {
        'label': '<i class="fa fa-bug"></i>Bug',
        'attr':{'class': 'btn btn-large btn-default btn-block' }
}) }}

Но, делая это, кнопка с расширенными правами выглядит следующим образом:

<button type="submit" name="SolveTask[taskTypesFormObj][bugStatus]"
    class="btn btn-large btn-default btn-block">
    &lt;i class=&quot;fa fa-bug&quot;&gt;&lt;/i&gt;Bug
</button>

Как вы можете видеть, html внутри кнопки закодирован. Я попытался использовать сырой фильтр, но эффект тот же. Есть ли способ сделать это?

Спасибо!

4b9b3361

Ответ 1

Да, но вам придется настроить тему своей формы.

Примечание.. Этот ответ был отредактирован для совместимости с Symfony 2.8 и 3.x. Для более старых версий см. Историю изменений.

Хорошим способом поддержки значков в кнопках является использование форм. Сначала создайте класс расширения формы, который определяет новый значок свойства, который вы можете использовать в своих формах:

<?php

namespace Foo\BarBundle\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\Type\ButtonType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ButtonTypeIconExtension extends AbstractTypeExtension
{
    /**
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->setAttribute('icon', $options['icon']);
    }

    /**
     * @param FormView      $view
     * @param FormInterface $form
     * @param array         $options
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['icon'] = $options['icon'];
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(['icon' => null]);
        $resolver->setDefined(['icon']);
    }

    /**
     * Returns the name of the type being extended.
     *
     * @return string The name of the type being extended
     */
    public function getExtendedType()
    {
        return ButtonType::class; // Extend the button field type
    }
}

Зарегистрируйте это расширение в файле services.yml(или xml). Псевдоним должен соответствовать строке, возвращаемой вышеуказанным методом getExtendedType().

# Form extention for adding icons
foobar.form_extention.icon:
    class: Foo\BarBundle\Form\Extension\ButtonTypeIconExtension
    tags:
        - { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\ButtonType }

Затем переопределите form_div_layout.html.twig. (См. Ссылку выше) Теперь вы можете использовать icon как переменную в этих темах. Для кнопок мы переопределяем блок button_widget:

{% block button_widget -%}
    {% set attr = attr|merge({class: (attr.class|default('') ~ ' btn')|trim}) %}
    {% if label is empty -%}
        {%- if label_format is not empty -%}
            {% set label = label_format|replace({
                '%name%': name,
                '%id%': id,
            }) %}
        {%- else -%}
            {% set label = name|humanize %}
        {%- endif -%}
    {%- endif -%}
    {% if icon|default %}
        {% set iconHtml = '<i class="fa ' ~ icon ~ '"></i> ' %}
    {% else %}
        {% set iconHtml = '' %}
    {% endif %}
    <button type="{{ type|default('button') }}" {{ block('button_attributes') }}>{{ iconHtml|raw }}{{ label|trans({}, translation_domain) }}</button>
{%- endblock button_widget %}

Наконец, вы можете использовать параметр значка в своем шаблоне:

{{ form_widget(form.jiraStatus, {
    'icon': 'fa-bug',
    'label': 'Bug',
    'attr':{'class': 'btn btn-large btn-default btn-block' }
}) }}

Или в ваших классах форм:

    $builder
        ->add('jiraStatus', SubmitType::class, [
                'label' => 'Bug',
                'icon' => 'fa-bug',
                'attr' => [
                    'class' => 'btn btn-large btn-default btn-block',
                ],
            ]
        );

Примечание. Как правило, лучше добавлять значок в шаблон, поскольку значки - это вопрос презентации, и ваши классы форм должны быть действительно логикой buisness.

Сделайте его еще более общим:

Вернув FQCN ButtonType в getExtendedType(), мы сообщаем Symfony, что мы расширяем все возможные элементы формы, которые наследуются от ButtonType, таких как SubmitType. К сожалению, нет типа, который мы можем использовать для таргетинга на все возможные элементы формы, но мы можем добавить дополнительное расширение, которое предназначено для FormType. Все поля формы, такие как поля ввода и элементы выбора, наследуются от этого типа. Поэтому, если вы хотите, чтобы он работал с полями и кнопками формы, я предлагаю следующее:

Создайте абстрактный класс abstract class AbstractIconExtension extends AbstractTypeExtension с точно таким же содержимым, как указано выше, но оставьте метод getExtendedType. Затем создайте два класса, которые простираются от этого класса (например, FieldTypeIconExtension и ButtonTypeIconExtension), которые содержат только метод getExtendedType. Один возвращает FQCN FormType, а другой возвращает FQCN ButtonType:

Foo/BarBundle/Форма/Extension/ButtonTypeIconExtension.php:

<?php

namespace Foo\BarBundle\Form\Extension;

use Symfony\Component\Form\Extension\Core\Type\ButtonType;

class ButtonTypeIconExtension extends AbstractIconExtension
{
    /**
     * Returns the name of the type being extended.
     *
     * @return string The name of the type being extended
     */
    public function getExtendedType()
    {
        return ButtonType::class;  // extend all buttons
    }
}

Foo/BarBundle/Форма/Extension/FieldTypeIconExtension.php:

<?php

namespace Foo\BarBundle\Form\Extension;

use Symfony\Component\Form\Extension\Core\Type\FormType;

class FieldTypeIconExtension extends AbstractIconExtension
{
    /**
     * Returns the name of the type being extended.
     *
     * @return string The name of the type being extended
     */
    public function getExtendedType()
    {
        return FormType::class;  // extend all field types
    }
}

Зарегистрируйте эти два класса в ваших службах, используя соответствующий псевдоним:

# Form extensions for adding icons to form elements
foobar.form_extention.button_icon:
    class: Foo\BarBundle\Form\Extension\ButtonTypeIconExtension
    tags:
        - { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\ButtonType }
foobar.form_extention.form_icon:
    class: Foo\BarBundle\Form\Extension\FieldTypeIconExtension
    tags:
        - { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }

Теперь вы можете использовать переменную icon в других местах в ваших тем формы. Например, чтобы добавить значки в метки, вы можете переопределить блок form_label:

{% block form_label -%}
    {% if label is not sameas(false) -%}
        {% if not compound -%}
            {% set label_attr = label_attr|merge({'for': id}) %}
        {%- endif %}
        {% if required -%}
            {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
        {%- endif %}
        {% if label is empty -%}
            {%- if label_format is not empty -%}
                {% set label = label_format|replace({
                    '%name%': name,
                    '%id%': id,
                }) %}
            {%- else -%}
                {% set label = name|humanize %}
            {%- endif -%}
        {%- endif -%}
        {% if icon|default %}
            {% set iconHtml = '<i class="fa ' ~ icon ~ '"></i> ' %}
        {% else %}
            {% set iconHtml = '' %}
        {% endif %}
        <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ iconHtml|raw }}{{ label|trans({}, translation_domain) }}</label>
    {%- endif %}
{%- endblock form_label %} 

Затем добавьте значок в метку этого поля в вашем классе формы:

$builder
    ->add('mytextfield', TextType::class, [
            'label' => 'My fancy text field',
            'icon' => 'fa-thumbs-o-up'
        ]
    );

Ответ 2

Если вы ищете более простое решение, просто вставьте его в свою тему :

{%- block button_widget -%}
    {% set attr = attr|merge({class: (attr.class|default('btn-default') ~ ' btn')|trim}) %}
    {%- if label is empty -%}
        {%- if label_format is not empty -%}
            {% set label = label_format|replace({
                '%name%': name,
                '%id%': id,
            }) %}
        {%- else -%}
            {% set label = name|humanize %}
        {%- endif -%}
    {%- endif -%}
    <button type="{{ type|default('button') }}" {{ block('button_attributes') }}>{{ label|trans({}, translation_domain)|raw }}</button>
{%- endblock button_widget -%}

Затем вы можете вставить HTML-код в свою метку:

{{ form_widget(searchForm.search, {'label': '<span class="glyphicon glyphicon-search" aria-hidden="true"></span>'}) }}

Ответ 3

Еще более простое решение может заключаться в том, чтобы оставить кнопки из типа формы и установить атрибуты name и value. Затем загрузите их, как и обычные параметры сообщения в контроллере.

В вашем шаблоне:

{{ form_start(form) }}

<button name="clicked" value="saveDraft" class="btn btn-warning">
  <i class="fa fa-square-o"></i> Save as Draft
</button>
<button name="clicked" value="saveComplete" class="btn btn-warning">
  <i class="fa fa-check-square-o"></i> Save as Complete
</button>

Затем в вашем контроллере

if ($form->isSubmitted() && $form->isValid()) {
    $clicked = $request->request->get('clicked');
}