Symfony twig how to add class to a form row

前端 未结 4 1508
情歌与酒
情歌与酒 2020-12-28 16:58

I am building a project in Symfony 2.3 using Twig. I want to add a class to the form row block. I am using a form theme file which contains:

{% block form_ro         


        
相关标签:
4条回答
  • 2020-12-28 17:39

    Docs say: you always able to pass attr to rendered element:

    {{ form_start(form, {'attr': {'class': 'your-class'}} ) }}
        {{ form_label(form, {'attr': {'class': 'your-class'}}) }}
        {{ form_widget(form, {'attr': {'class': 'your-class'}}) }}
        {{ form_errors(form, {'attr': {'class': 'your-class'}}) }}
    {{ form_end(form) }}
    
    0 讨论(0)
  • 2020-12-28 17:41

    Below is a clone of answer by @lopsided but with changes reflecting latest Symfony structure changes (v. 2.7+):


    There is a fairly simple solution to this problem actually. I just needed a form type extension to extend the base form type to allow an extra available option: http://symfony.com/doc/master/form/create_form_type_extension.html

    Following through the example in the docs, I created a new form type extension:

    // src/Acme/FrontendBundle/Form/Extension/FormTypeExtension.php
    
    namespace Acme\FrontendBundle\Form\Extension;
    
    use Symfony\Component\Form\AbstractTypeExtension;
    use Symfony\Component\Form\FormInterface;
    use Symfony\Component\Form\FormView;
    use Symfony\Component\Form\Extension\Core\Type\FormType;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    
    /**
     * Class FormTypeExtension
     * @package Acme\FrontendBundle\Form\Extension
     */
    class FormTypeExtension extends AbstractTypeExtension
    {
        /**
         * Extends the form type which all other types extend
         *
         * @return string The name of the type being extended
         */
        public function getExtendedType()
        {
            return FormType::class;
        }
    
        /**
         * Add the extra row_attr option
         *
         * @param OptionsResolver $resolver
         */
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(array(
                'row_attr' => []
            ));
        }
    
        /**
         * Pass the set row_attr options to the view
         *
         * @param FormView $view
         * @param FormInterface $form
         * @param array $options
         */
        public function buildView(FormView $view, FormInterface $form, array $options)
        {
            $view->vars['row_attr'] = $options['row_attr'];
        }
    }
    

    Then I registered the service in my bundle...

    <!-- Form row attributes form extension -->
    <service id="acme.form_type_extension" class="Acme\FrontendBundle\Form\Extension\FormTypeExtension">
        <tag name="form.type_extension" alias="form" extended_type="Symfony\Component\Form\Extension\Core\Type\FormType" />
    </service>
    

    Since every widget extends the base form type this then allows me to pass this new row_attr option through on any field, eg:

    $builder
        ->add('first_name', TextType:class, [
            'row_attr' => [
                'class' => 'form-row-split'
            ]
        ]);
    

    Then the twig overrides to make use of the new row_attr option:

    {% block form_row %}
        <div {{ block('form_row_attributes') }}>
            {{ form_label(form) }}
            {{ form_widget(form) }}
            {{ form_errors(form) }}
        </div>
    {% endblock form_row %}
    
    {% block form_row_attributes %}
        {% spaceless %}
            {% for attrname, attrvalue in row_attr %}{{ attrname }}="{{ attrvalue }}" {% endfor %}
        {% endspaceless %}
    {% endblock form_row_attributes %}
    

    And it's done!

    (For completeness, my full twig override still merges in the form-row and error classes in like so:

    {% set row_attr = row_attr|merge({'class': 'form-row' ~ (row_attr.class is defined ? ' ' ~ row_attr.class : '') ~ (errors|length > 0 ? ' error' : '')} ) %}
    

    .. but thats not really necessary for answering my own question :P )

    0 讨论(0)
  • 2020-12-28 17:43

    What I did was simpler (though maybe a bit less clean?).

    Pass the class for the form row via a field's "data" attribute :

    // template.html.twig
    
    {{ form_start(form) }}
        {{ form_row(form.field, {'attr': {'data-row-class': 'my-row-class'} }) }}
    {{ form_end(form) }}
    

    And then handle it in the form theme template this way :

    // form-theme.html.twig
    
    {% block form_row -%}
        {% set row_class = attr['data-row-class'] | default('') %}
        <div class="{{ row_class }}">
            {{- form_label(form) -}}
            {{- form_widget(form) -}}
            {{- form_errors(form) -}}
        </div>
    {%- endblock form_row %}
    

    Which gives this :

    <form name="formName" method="post">
        <div class="my-row-class">
            <label for="formName_field">Field label</label>
            <input type="text" id="formName_field" name="formName[field]" data-row-class="my-row-class">
        </div>
    </form>
    
    0 讨论(0)
  • 2020-12-28 17:44

    There is a fairly simple solution to this problem actually. I just needed a form type extension to extend the base form type to allow an extra available option: http://symfony.com/doc/2.3/cookbook/form/create_form_type_extension.html

    Following through the example in the docs, I created a new form type extension:

    // src/Acme/FrontendBundle/Form/Extension/FormTypeExtension.php
    
    namespace Acme\FrontendBundle\Form\Extension;
    
    use Symfony\Component\Form\AbstractTypeExtension;
    use Symfony\Component\Form\FormInterface;
    use Symfony\Component\Form\FormView;
    use Symfony\Component\OptionsResolver\OptionsResolverInterface;
    
    /**
     * Class FormTypeExtension
     * @package Acme\FrontendBundle\Form\Extension
     */
    class FormTypeExtension extends AbstractTypeExtension
    {
        /**
         * Extends the form type which all other types extend
         *
         * @return string The name of the type being extended
         */
        public function getExtendedType()
        {
            return 'form';
        }
    
        /**
         * Add the extra row_attr option
         *
         * @param OptionsResolverInterface $resolver
         */
        public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setDefaults(array(
                'row_attr' => array()
            ));
        }
    
        /**
         * Pass the set row_attr options to the view
         *
         * @param FormView $view
         * @param FormInterface $form
         * @param array $options
         */
        public function buildView(FormView $view, FormInterface $form, array $options)
        {
            $view->vars['row_attr'] = $options['row_attr'];
        }
    }
    

    Then I registered the service in my bundle...

    <!-- Form row attributes form extension -->
    <service id="acme.form_type_extension" class="Acme\FrontendBundle\Form\Extension\FormTypeExtension">
        <tag name="form.type_extension" alias="form" />
    </service>
    

    Since every widget extends the base form type this then allows me to pass this new row_attr option through on any field, eg:

    $builder
        ->add('first_name', 'text', array(
            'row_attr' => array(
                'class' => 'form-row-split'
            )
        ));
    

    Then the twig overrides to make use of the new row_attr option:

    {% block form_row %}
        <div {{ block('form_row_attributes') }}>
            {{ form_label(form) }}
            {{ form_widget(form) }}
            {{ form_errors(form) }}
        </div>
    {% endblock form_row %}
    
    {% block form_row_attributes %}
        {% spaceless %}
            {% for attrname, attrvalue in row_attr %}{{ attrname }}="{{ attrvalue }}" {% endfor %}
        {% endspaceless %}
    {% endblock form_row_attributes %}
    

    And it's done!

    (For completeness, my full twig override still merges in the form-row and error classes in like so:

    {% set row_attr = row_attr|merge({'class': 'form-row' ~ (row_attr.class is defined ? ' ' ~ row_attr.class : '') ~ (errors|length > 0 ? ' error' : '')} ) %}
    

    .. but thats not really necessary for answering my own question :P )

    0 讨论(0)
提交回复
热议问题