Symfony: How to avoid automatically creating custom form types wrapped in divs?

UserType form:

class UserType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('email', 'email', ['label' => 'EMail']); // various other fields.... } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'validation_groups' => array('registration'), 'data_class' => 'Vendor\Model\Entity\User', )); } public function getName() { return 'form_user'; } } 

TutorType form:

 class TutorType extends Translate { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('user', new UserType(), ['label' => false]); $builder->add('school', 'entity', [ 'class' => 'Model:School', 'property' => 'name', 'label' => 'Label' ]); // Various other fields $builder->add('save', 'Submit'); } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( //'validation_groups' => array('registration'), 'data_class' => 'Vendor\Model\Entity\Tutor', 'cascade_validation' => true, )); } public function getName() { return 'form_tutor'; } } 

When rendering UserType displayed inside a div, I cannot find a way to overcome this.

The form is displayed as

the result

 <form name="form_tutor" method="post" action="" novalidate="novalidate" class="form-horizontal form-horizontal" id="form_tutor"> <div id="form_tutor" novalidate="novalidate" class="form-horizontal"> <div class="form-group"> <div class="col-lg-10"> <div id="form_tutor_user"> <div class="form-group"> <label class="col-lg-2 control-label aaaa required" for="form_tutor_user_email">EMail</label> <div class="col-lg-10"> <input type="email" id="form_tutor_user_email" name="form_tutor[user][email]" required="required" class="form-control" /> </div> </div> </div> </div> </div> <div class="form-group"> <label class="col-lg-2 control-label aaaa required" for="form_tutor_tutorType">Type</label> <div class="col-lg-10"> <select id="form_tutor_tutorType" name="form_tutor[tutorType]" class="form-control"> </select> </div> </div> <div class="form-group"> <div class="col-lg-offset-2 col-lg-10"> <button type="submit" id="form_tutor_save" name="form_tutor[save]" class="btn btn-default">Speichern</button> </div> </div><input type="hidden" id="form_tutor__token" name="form_tutor[_token]" class="form-control" value="s6i6zPxJs7KU5CiEe8i6Ahg_ca8rc2t5CnSk5yAsUhk" /> </div> </form> 

form_tutor_user in its own form group div. I tried to overwrite form_tutor_user_widget, but this is one level to depth. (And only a quick fix, it should be globally applied to all types of form - Classes)

How can I change the theme so that all user types are not wrapped by the default form_row template?

Or how can I find out in a branch when "subordinate" is displayed? so I can decide to print <div class="form-group"> when the child-node is not a subform or skip it if it is.

TIA

+8
symfony twig symfony-forms
source share
5 answers

By default in the base theme form:

 {% block form_row %} {% spaceless %} <div> {{ form_label(form) }} {{ form_errors(form) }} {{ form_widget(form) }} </div> {% endspaceless %} {% endblock form_row %} 

And for custom compound forms:

 {% block form_widget_compound %} {% spaceless %} <div {{ block('widget_container_attributes') }}> {% if form.parent is empty %} {{ form_errors(form) }} {% endif %} {{ block('form_rows') }} {{ form_rest(form) }} </div> {% endspaceless %} {% endblock form_widget_compound %} 

If you have not changed anything here, the DIV that you see should come from one or the other bit of the template.

However, in your specific example, if form_tutor_user_row is defined, the first bit is never used, and if form_tutor_user_widget is defined, the last bit is never used.

Let's get back to your question. Your question: "How can I change the theme so that all user types are not wrapped by the default form_row form template?"

This is the problem, as I see it: you want your TOP-forms (the form in which all sub-forms were included) to have a common way of rendering in sections. Each section will be included in the DIV with class = "form-group". You might want to add some additional rendering operations, but I will limit myself to keeping things simple.

What you need to do is create the type of the specified form and make all of your TOP forms inherited from this new form type. For example:

 class TopType extends AbstractType { public function getName() { return 'top_form'; } } 

... and the inherited form:

 class MyFormType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { ... } public function getName() { return 'my_form'; } public function getParent() { return 'top_form'; } } 

As you can see, there is no need to inherit PHP inheritance for type inheritance inheritance.

The-theming-wise template (can I even say this?), If my_form is not given a specific form task, Symfony will understand that the default form theme to use here is the top_form form theme , which you can define as such:

 {% block top_form_widget %} {% spaceless %} {% for child in form %} <div class="form-group"> {{ form_widget(child) }} </div> {% endfor %} {{ form_rest(form) }} {% endspaceless %} {% endblock top_form_widget %} 

I must add that this is a problem that I have already encountered and solved. Tell us how it works for you.

Edit:

To summarize, you need to do the following:

  • Create a TopType form type,
  • Add a top_form_widget block in the form theme,
  • For all your root forms (i.e. top-level forms, forms that don't have a parent) add a getParent () method that will return your TopType form name ("top_form")
+4
source share

I usually solve this problem by manually creating nested form fields:

 {{ form_row(form.tutor.school) }} {{ form_row(form.tutor.user.email) }} 

This may not be the most elegant solution, but it works for me, and I have not yet looked for an elegant one.

+3
source share

In theory, if you redefine the form_widget_compound block in the global theme form in this way, it should work the way you want:

 // app/Resources/views/form.html.twig {% block form_widget_compound %} {% if form.parent is empty %} <div {{ block('widget_container_attributes') }}> {{ form_errors(form) }} {% endif %} {{ block('form_rows') }} {{ form_rest(form) }} {% if form.parent is empty %} </div> {% endif %} {% endblock %} 

And register the theme of your form:

 // app/config/config.yml twig: form: resources: - "::form.html.twig" 
+2
source share

This may not be an elegant solution, but it works for me because I also tried to find a solution.

As an example:

 {% for custom_field in form.custom_fields %} <div class="edit_custom"> {{ form_row(custom_field.name) }} {{ form_row(custom_field.value) }} </div> {% endfor %} <script> $('.edit_custom').find('input').unwrap(); </script> 
0
source share

Try using form_themes.

First, in the parent template, specify the form theme:

 {% form_theme form with ['BundleName:ControlerName:somesubform_form.html.twig'] %} 

btw replace BundleName, ControllerName and somesubform with names.

then draw it with:

 {{ form_row(form.somesubform) }} 
-one
source share

All Articles