Twig を使って Symfony フォームボタン内に HTML を配置できますか? 質問する

Twig を使って Symfony フォームボタン内に HTML を配置できますか? 質問する

次のように、Twig を使用してフォーム ボタン内に HTML を配置しようとしています。

{{ 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 はエンコードされています。raw フィルターを使用しようとしましたが、効果は同じです。これを行う方法はありますか?

ありがとう!

ベストアンサー1

はい、カスタマイズする必要がありますフォームのテーマ

注記:この回答は、Symfony 2.8 3.x および 4.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\OptionsResolver;

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 extension for adding icons
foobar.form_extension.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使用できるようになりました。 ボタンの場合は、ブロックをオーバーライドします。iconbutton_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',
                ],
            ]
        );

注: アイコンはプレゼンテーションの問題であり、フォーム クラスは実際にはビジネス ロジックに関するものである必要があるため、通常はテンプレートにアイコンを追加する方が適切です。

さらに一般的な例を挙げます。

getExtendedType() で ButtonType の FQCN を返すことで、Symfony に継承可能なすべてのフォーム要素を拡張していることを伝えます。ボタンタイプのような送信タイプ残念ながら、すべてのフォーム要素をターゲットにできるタイプはありませんが、ターゲットとする追加の拡張機能を追加することができます。フォームタイプ入力ボックスや選択要素などのすべてのフォームフィールドはこのタイプを継承します。したがって、両方のフォームフィールドで動作させたい場合そしてボタンについては、次のことをお勧めします。

abstract class AbstractIconExtension extends AbstractTypeExtension上記とまったく同じ内容の抽象クラスを作成しますが、getExtendedTypeメソッドは除きます。次に、このクラスから拡張する 2 つのクラス (たとえば、FieldTypeIconExtensionButtonTypeIconExtension) を作成します。これらのクラスには メソッドのみが含まれますgetExtendedType。1 つは の FQCN を返しFormType、もう 1 つは の FQCN を返しますButtonType

Foo/BarBundle/Form/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/Form/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
    }
}

対応するエイリアスを使用して、これらの 2 つのクラスをサービスに登録します。

# Form extensions for adding icons to form elements
foobar.form_extension.button_icon:
    class: Foo\BarBundle\Form\Extension\ButtonTypeIconExtension
    tags:
        - { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\ButtonType }
foobar.form_extension.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'
        ]
    );

おすすめ記事