Submit Button is not rendered in Symfony 2.x Form - forms

I'm creating a from using Symfony Form builder, and rendering it using twig.
Here is my form builder code:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', 'text', array(
'required' => TRUE,
))
->add('link', 'text', array(
'required' => TRUE,
))
->add('submit', 'submit', array(
'attr' => array(
'class' => 'btn btn-primary btn-sm custom-btn'
)
))
;
}
And my twig template is like this:
{{ form_start(form)}}
<div>
{{ form_label(form.name) }}
{{ form_widget(form.name) }}
</div>
<div>
{{ form_label(form.link) }}
{{ form_widget(form.link) }}
</div>
<div>
{{ form_widget(form.submit) }}
</div>
{{ form_end(form) }}
In this case, I'm getting everything as expected, except the submit button. Instead of custom submit button created in form builder, it is rendering default submit button with a label create.
What I'm doing wrong here?

Seems it is some issue with 'submit' name. For example, next example works:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
.... // your fields here
->('my_button', 'submit');
}
Then in the twig template:
<div>
{{ form_widget(form.my_button) }}
</div>
UPDATED : according to http://symfony.com/doc/current/reference/forms/twig_reference.html you can use {{ form_widget(form.submit, {'label': 'submit'}) }}. So next lines renders submit with 'submit' name:
{{ form_start(form) }}
{{ form_widget(form.text) }}
{{ form_widget(form.code) }}
{{ form_widget(form.submit, {'label': 'submit'}) }}
{{ form_end(form) }}
And you don't need to add submit to your FormType in this case.

Related

Symfony form CollectionType render the label only once

I have a SquadType form which contains an embedded SquadMemberType form as a collectionType field.
Each time I press the add squad member button on my form, I can add a squadMember form from the prototype. Works perfectly.
The fact is, each time I add a squadMember form, it displays the name and tag label. I want to find a way to display these labels only for the first squadMember but not for the others.
I tried to set label to false in the form squadMemberType class and to display it directly in the template with no success (didn't find a way to make it work).
Is there a way to achieve that ?
My main form :
class squadType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('squadName', TextType::class)
->add('squadDescription', TextareaType::class)
->add('squadMembers', CollectionType::class, [
'label' => ' ',
'entry_type' => SquadMemberType::class,
'entry_options' => [
'attr' => [
'class' => 'email-box',
'style' => 'display:flex; gap:1rem;',
]
],
'allow_add' => true,
])
->add(
'save',
SubmitType::class, ['label' => 'Create Squad']
)
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Squad::class,
]);
}
}
My embedded form :
class SquadMemberType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('squadMemberName', TextType::class, [
'label_attr' => [
'class' => 'formLabel',
],
'label' => 'Name',
])
->add('squadMemberTag', IntegerType::class, [
'label' => 'Tag',
// 'label' => false,
'label_attr' => [
'class' => 'formLabel',
],
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => SquadMember::class,
]);
}
}
My twig :
<div class="content">
{{ form_start(form, {'attr': {'class': 'form-horizontal', 'id': 'create-squad'}}) }}
<div class="creation-form">
<fieldset class="creation-form-globalInfo">
<div class="form-group {{ form.squadName.vars.valid==false ? "has-error" }}">
{{ form_label(form.squadName, null, {
'label': 'Squad Name',
'label_attr': {'class': 'control-label'}}) }}
<div class="">
{{ form_widget(form.squadName) }}
{{ form_errors(form.squadName) }}
</div>
</div>
<div class="form-group {{ form.squadDescription.vars.valid==false ? "has-error" }}">
{{ form_label(form.squadDescription, null, {
'label': 'Squad Description',
'label_attr': {'class': 'control-label'}}) }}
<div class="">
{{ form_widget(form.squadDescription) }}
{{ form_errors(form.squadDescription) }}
</div>
</div>
</fieldset>
<fieldset class="creation-form-info">
<ul id="squadMember-fields-list"
data-prototype="{{ form_widget(form.squadMembers.vars.prototype)|e }}"
data-widget-tags="{{ '<li></li>'|e }}"
data-widget-counter="{{ form.squadMembers|length }}"
class="squad-form">
{% for squadMemberField in form.squadMembers %}
<li>
{{ form_errors(squadMemberField) }}
{{ form_widget(squadMemberField) }}
</li>
{% endfor %}
</ul>
<button type="button"
class="add-another-collection-widget secundary-button"
data-list-selector="squadMember-fields-list">
{{ 'squad.add.squadMember.button.label'|trans }}
</button>
</fieldset>
</div>
<div class="validation-bottom">
{{ form_row(form.save,{
'label': 'squad.add.confirm.button',
'attr': {
'class': 'primary-button'
}
})
}}
</div>
{{ form_end(form) }}
</div>
my script :
{% block javascripts %}
<script>
$(document).ready( function () {
$('.add-another-collection-widget').click(function (e) {
var list = jQuery(jQuery(this).attr('data-list-selector'));
// Try to find the counter of the list or use the length of the list
var counter = list.data('widget-counter') || list.children().length;
// grab the prototype template
var newWidget = list.attr('data-prototype');
// replace the "__name__" used in the id and name of the prototype
// with a number that's unique to your emails
// end name attribute looks like name="contact[emails][2]"
newWidget = newWidget.replace(/__name__/g, counter);
// Increase the counter
counter++;
// And store it, the length cannot be used if deleting widgets is allowed
list.data('widget-counter', counter);
// create a new list element and add it to the list
var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget);
newElem.appendTo(list);
});
</script>
{% endblock %}

Why does Symfony 3.4 form displays EntityType choices with label although 'label' => false was used?

I am working on an existing Symfony 3.4 based project and trying to add and render a new form. Although the 'label' => false option was used, the fields are rendered including a label. Why?
// Symfony
class SomeController extends Controller {
public function userListAction(Request $request) {
$users = $someService->getUsers();
$formBuilder = $this->createFormBuilder()
->add('users', EntityType::class, [
'label' => false, // also tested '' and 'someLabel'
'class' => 'AppBundle:User',
'choices' => $users,
'multiple' => true,
'expanded' => true,
]);
$variables = array(
'form' => $formBuilder->getForm()->createView(),
);
return $this->render('AppBundle:Pages:user_list.html.twig', $variables);
}
}
// Twig
{% extends 'AppBundle::layout.html.twig' %}
{% block page_content %}
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
{% endblock %}
This shows a list of checkboxes for all users including the username as label.
Where does Symfony get the information to use the username as label? As far as I know no custom form widget was defined for the User class. Is there any way to check this for sure? Maybe there is something hidden in the vendor bundles like FOSUserBundle?
Why is the 'label' => false option ignored?
Edit:
Different ways of rendering the form does not solve the problem:
{{ form_start(form) }}
{{ form_row(form) }}
{{ form_end(form) }}
Result:
<div id="form_users">
<div class="form-group">
<div class="checkbox">
<label for="form_users_547">
<input type="checkbox" id="form_users_547" name="form[users][]" value="547">
someUserName
</label>
</div>
</div>
</div>
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
Result:
<div id="form_users">
<div class="checkbox">
<label for="form_users_547">
<input type="checkbox" id="form_users_547" name="form[users][]" value="547">
someUserName
</label>
</div>
</div>
{{ form_start(form) }}
{% for userFormView in form.users %}
{{ form_row(userFormView) }}
{% endfor %}
{{ form_end(form) }}
Result:
Basically the same as before with form_row
You need to use ‘choice_label’ => ‘YOUR PROPERTY PATH’ in the field options.
Pretty match is written in the docs: https://symfony.com/doc/current/reference/forms/types/entity.html#choice-label
If the entity class cast to string then is used if is not it will throw an exception. It looks like your entity User cast to the user name and that’s why it works.
You should try to use {{ form_row(form) }} which should render the whole field correctly.

Braincrafted bootstrapbundle set input size

I'm using braincrafted BootstrapBundle.
How do i get it to render inputs using input-sm?
I have scoured the docs but only seems to be setting for col sizes and not for inputs.
Here in Italy we say to do as the ancients did.
For your needs braincrafted has nothing to offer then you just add the class to the input field to achieve your needs
{{ form_start(form, {attr:{class: 'input-sm'} }) }}
{{ form_widget(form.username, {attr:{class: 'input-sm', placeholder: 'username'} }) }}
<div class="form-group">
{{ form_widget(form.password, {attr:{class: 'input-sm', placeholder: 'password'} }) }}
{{ form_widget(form.submit, {attr:{class: 'btn btn-primary btn-sm'} }) }}
</div>
{{ form_end(form) }}
{{ form_widget(form.field, {attr:{class: 'input-sm'} }) }}
or in your builder
$builder->add(
'field',
'text',
array(
'attr' => array(
'class' => 'input-sm',
'placeholder' => 'Fill it',
),
'required' => true
)
);

problems with request in a embed form

HEllo sorry but my english isnt good.
I'm developing an application in Symfony 2.3.6 where i have to save in a DB (postgres) the values from a user.
The problem happens when my embed form (pais + region) that has 2 submit buttons the user press the second button. The system throw
Child "salvar_region" does not exist.
The question is how can I detect if the second button is being pressed if the system is throwing an exception?
Here is my Default controller
public function addLocalAction(Request $request)
{
$region = new Region();
$localidad = new Pais();
$localidad->setRegion($region);
$form = $this->createForm(new localidadType(), $localidad);
if($request->isMethod('POST')){
$form->handleRequest($request);
$form->getData();
if ($form->get('salvarPais')-> isClicked()){
$objeto = new Pais();
$objeto->setNombrePais($form->get('nombrePais')->getData());
$em = $this->getDoctrine()->getManager();
$em->persist($objeto);
$em->flush();}
if ($form->get('salvarregion')->isClicked()){
$objeto = new Region();
$objeto->setNombreRegion($form->get('nombreRegion')->getData());
$objeto->setNombreRegion($form->get('numeroRegion')->getData());
$em = $this->getDoctrine()->getManager();
$em->persist($objeto);
$em->flush();}
return $this->redirect($this->generateUrl('localidades'));
}
return $this->render('plataformaPlataformaBundle:Default:localidades.html.twig', array('form'=> $form->createView()));
}
My html.twig
<form action="{{ path('localidades')}}" method="post" {{ form_enctype(form) }}>
<h3>Agregar País</h3>
<div class="pais">
{{ form_row(form.nombrePais) }}
{{ form_row(form.salvarPais) }}
</div>
<form action="{{ path('localidades')}}" method="post" {{ form_enctype(form) }}>
<h3>Agregar Region</h3>
<div class="region">
{{ form_start(form) }}
{{ form_errors(form)}}
{{ form_row(form.region.nombreRegion) }}
{{ form_row(form.region.numeroRegion) }}
{{ form_row(form.region.pais) }}
{{ form_row(form.region.salvarregion) }}
{{ form_end(form) }}
</div>
</form>
and my 2 type forms
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('nombreRegion', 'text', array('label' => 'Nombre de Región: '));
$builder->add('numeroRegion', 'integer', array('label' => 'Número de Región: '));
$builder->add('pais', 'entity', array('label' => 'País al que pertenece: ',
'class' => 'plataformaPlataformaBundle:Pais',
'property' => 'nombrePais'));
$builder->add('salvarregion', 'submit', array('label' => 'Guardar Región'));
$builder->getForm();
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('nombrePais', 'text');
$builder->add('salvarPais', 'submit', array('label' => 'Guardar País'));
$builder->add('region', new regionType());
$builder->getForm();
}
PD: A lot of thanks if someone can help me
PDx2: here is an example of the URL request:{"region":{"nombreRegion":"ewrew","numeroRegion":"4","pais":"3","salvarregion":""},"_token":"853d5460b076e01fdf4cef4c59c33e836ab64af3"}
The error you got doesn't look like the name you gave the button during the builder process.
Anyway, to tell if a specific submit was clicked you can use:
if($form->get('salvarregion')->isClicked()) {
}

How to display multiple informations of another entity in the same form?

Actually, I try to create a form on middle entity and I want to display many input for the same entity (project color and project name). I would be able to create the project entity too.
# MyNiceBundle/Form/Type/CollaborationType.php
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('project', 'entity', array(
'class' => 'MyNiceBundle:Project',
'property' => 'name'
));
$builder->add('project', 'entity', array(
'class' => 'MyNiceBundle:Project',
'property' => 'color'
));
$builder->add('participant', 'entity', array(
'class' => 'MyNiceBundle:User',
'property' => 'email',
'multiple' => true,
'expanded' => true
));
$builder->add('workgroup', 'entity', array(
'class' => 'MyNiceBundle:Workgroup',
'property' => 'name',
'multiple' => false,
'expanded' => true
));
}
# Resources/Views/project_form.html.twig
<form id="project-creation" class="form" action="{{ path('nicebundle_project_create') }}" method="post">
{{ form_errors(form) }}
<div class="project">
# Here I want to show the input for project name
{{ form_errors(form.project) }}
{{ form_widget(form.project) }}
</div>
<div id="navigation-panel">
# Here I want to show the input for project color
{{ form_errors(form.project) }}
{{ form_widget(form.project) }}
{{ form_errors(form.participant) }}
{{ form_widget(form.workgroup) }}
{{ form_widget(form._token) }}
<input class="btn" type="reset" value="reset" />
<input class="btn" type="submit" value="submit" />
</div>
</form>
What should I do?
Thanks in advance.
I passed the ProjectType in the CollaborationType like that:
# MyNiceBundle/Form/Type/CollaborationType.php
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('project', new ProjectType());
$builder->add('participant', 'entity', array(
'class' => 'BtaskUserBundle:User',
'property' => 'email',
'multiple' => false,
'expanded' => true
));
$builder->add('workgroup', 'entity', array(
'class' => 'BtaskBoardBundle:Workgroup',
'property' => 'name',
'multiple' => false,
'expanded' => true
));
}
# Resources/Views/project_form.html.twig
<form id="workgroup-form-create" class="form" action="{{ path('MyNiceBundle_project_create') }}" method="post" {{ form_enctype(form) }}>
{{ form_errors(form) }}
<div class="project">
{{ form_errors(form.project) }}
{{ form_widget(form.project) }}
</div>
<div id="navigation-panel">
{{ form_errors(form.project) }}
{{ form_widget(form.project) }}
{{ form_errors(form.participant) }}
{{ form_widget(form.participant) }}
{{ form_errors(form.workgroup) }}
{{ form_widget(form.workgroup) }}
{{ form_widget(form._token) }}
<input class="btn" type="reset" value="reset" />
<input class="btn" type="submit" value="submit" />
</div>
</form>