Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I put html inside a Symfony form button with Twig?

Tags:

twig

symfony

I'm trying to put html inside a form button with twig like:

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

But doing this, the rendeded button shows like this:

<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> 

As you can see, the html inside the button is encoded. I tried to use the raw filter, but the effect is the same. There is a way to do this?

Thanks!

like image 851
viscat Avatar asked Jan 12 '15 15:01

viscat


People also ask

Can we write PHP code in Twig file?

Replied by DenisChenu on topic Can I write PHP code in Twig Template? No, It's the reason of twig : don't give all PHP power with a simple editor.

Is Twig a Symfony?

Twig is a PHP template engine. It was created by Symfony developers. Twig files have the extension of . html.

What is Twig HTML?

Twig is a modern template engine for PHP This allows Twig to be used as a template language for applications where users may modify the template design. Flexible: Twig is powered by a flexible lexer and parser. This allows the developer to define its own custom tags and filters, and create its own DSL.


1 Answers

Yes, but you'll have to customise your form theme.

Note: This answer has been edited to be compatible with Symfony 2.8 3.x and 4.x. For older versions, please see the edit history.

A nice way to support icons in buttons is using form extensions. First create a form extension class that defines a new property icon that you can use in your forms:

<?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     } } 

Register this extension in your services.yml (or xml file). The alias must correspond with the string returned by the above getExtendedType() method.

# 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 } 

Next, override your form_div_layout.html.twig. (See link above) You can now use icon as a variable in these themes. For buttons we override the button_widget block:

{% 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 %} 

Finally, you can use the icon option in your template:

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

Or in your form classes:

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

Note: Is is generally better to add the icon in the template since icons are a matter of presentation, and your form classes should really be about buisness logic.

Make it even more generic:

By returning the FQCN of ButtonType in getExtendedType() we tell Symfony that we are extending all possible form elements that inherit from ButtonType such as SubmitType. Unfortunately there is no type we can use to target all possible form elements but we can add an extra extension that targets FormType. All form fields like input boxes and select elements inherit from this type. So if you want it to work with both form fields and buttons, I suggest the following:

Create an abstract class abstract class AbstractIconExtension extends AbstractTypeExtension with exactly the same content as above but leave out the getExtendedType method. Then create two classes that extend from this class (e.g. FieldTypeIconExtension and ButtonTypeIconExtension) which only contain the getExtendedType method. One returning the FQCN of FormType and the other returning the FQCN of 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     } } 

Register these two classes in you services using the corresponding alias:

# 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 } 

Now you can use the icon variable in other places in your form themes as well. For instance, to add icons to labels you can override the form_label block:

{% 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 %}  

And then add an icon to the label of that field in your form class:

$builder     ->add('mytextfield', TextType::class, [             'label' => 'My fancy text field',             'icon' => 'fa-thumbs-o-up'         ]     ); 
like image 120
Xatoo Avatar answered Sep 21 '22 23:09

Xatoo