I have seen various posts regarding same issue but nothing could become useful for me.
This is my Form
<form action="" method="post" {{ form_enctype(form) }} novalidate>
{{ form_errors(form) }}
<div class="login_field">
{{ form_label(form.name) }}
{{ form_widget(form.name) }}
</div>
<div class="clear"></div>
<div class="login_field">
{{ form_label(form.status) }}
{{ form_widget(form.status) }}
</div>
<div class="login_field">
<label> </label>
<input type="submit" value="Create" class="submit_btn" />
</div>
</form>
Error are not being displayed at all. How can i get out of this issue?
You have to include form_errors for every field ...
<div class="login_field">
{{ form_errors(form.name) }}
{{ form_label(form.name) }}
{{ form_widget(form.name) }}
</div>
... or just use form_row to render all the three of them together ...
<div class="login_field">
{{ form_row(form.name) }}
</div>
... or let your form errors bubble up to the top using the error_bubbling option for your form-fields in your FormType class. This means they will then be rendered through {{ form_errors(form) }}.
$builder->add('fieldname', 'text', array(
'error_bubbling' => true,
));
quick tip: you can include the submit button in your FormType since symfony 2.3 and don't have to manually render it (reference).
To display all the errors at top of form do like below
<ul>
{% for error in form.vars.errors.form.getErrors(true) %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
Related
I am rendering a form inside a twig file. I just want to add a default/selected option to the select field and I need to do it inside the twig rather than controller, entity, or the formType.
Here is the code in my twig file:
{{ form_start(prdForm) }}
<div class="form-group">
{{ form_row(prdForm.productTitle, {'label': "Product Title", 'attr': {'placeholder': "Enter Product Name", 'class': "form-control"}}) }}
</div>
<div class="form-group">
{{ form_row(prdForm.productDescription, {'label': "Description", 'attr': {'placeholder': "Provide a short description for this product.", 'class': "form-control"}}) }}
</div>
<div class="form-group">
<option value="" selected="selected" disabled="disabled">Choose an item...</option>
{{ form_widget(prdForm.category, {'label': "Select Category", 'attr': {'class': "form-control"} }) }}
</div>
{{ form_end(prdForm) }}
you can use choice type inside your form. take look on this https://symfony.com/doc/current/reference/forms/types/choice.html#example-usage
cheers
Ok, here is the solution to add a placeholder option into your select field within the twig file, not the best answer but at least it works:
{% do prdForm.category.setRendered %}
<div class="form-group">
<label for="{{prdForm.children.category.vars.id}}" class="required">Category</label>
<select name="{{ prdForm.children.category.vars.full_name }}" id="{{prdForm.children.category.vars.id}}" class="form-control">
<option value="" selected="selected" disabled="disabled">Choose a category</option>
{% for option in prdForm.children.category.vars.choices %}
<option value="{{option.value}}">{{option.label}}</option>
{% endfor %}
</select>
</div>
Of course, thanks to another user for his answer here:
Placeholder for form_widget choices on Twig
I have a list of checkbox created in a form with the following
->add('ISPreNbStudents', ChoiceType::class, [
'multiple' => false,
'choices' => [
'1' => 1,
'2' => 2,
'3' => 3,
'4' => 4,
'5' => 5,
],
'expanded' => true
])
I can then display this in the twig file with this : {{ form_widget(form.ISOptMonths) }}
The problem is that it now display a list of label and input like this
<input type="radio" id="availability_ISPreNbStudents_0" name="availability[ISPreNbStudents]" value="1">
<label for="availability_ISPreNbStudents_0">1</label>
<input type="radio" id="availability_ISPreNbStudents_1" name="availability[ISPreNbStudents]" value="2">
<label for="availability_ISPreNbStudents_1">2</label>
I need to put wrapper around each label/input like this
<div class="styled-input-single">
<input type="checkbox" name="case-1" id="1" />
<label for="1">1</label>
</div>
<div class="styled-input-single">
<input type="checkbox" name="case-2" id="2" />
<label for="2">2</label>
</div>
How can I achieve this ?
I've finally found the solution :
Here is how you print your list :
{{ form_row(registrationForm.firstRecourse) }}
Now is you want to add wrapper around every option :
<div class="row">
{{ form_label(registrationForm.ISPreNbStudents) }}
{% for checkbox in registrationForm.ISPreNbStudents.children %}
<div class="styled-input-single">
{{ form_widget(checkbox) }}
{{ form_label(checkbox) }}
{{ form_errors(checkbox) }}
</div>
{% endfor %}
</div>
You have to use Symfony Customize Form Rendering.
This way you can access your form field by field, like:
{{ form_start(form) }}
<div class="my-custom-class-for-errors">
{{ form_errors(form) }}
</div>
<div class="row">
<div class="col">
{{ form_row(form.task) }}
</div>
<div class="col" id="some-custom-id">
{{ form_row(form.dueDate) }}
</div>
</div>
{{ form_end(form) }}
You are able to render the fields manually also:
<div class="styled-input-single">
{{ form_widget(form.name_of_form_element) }}
{{ form_label(form.name_of_form_element) }}
<!-- and for errors of this field -->
{{ form_errors(form.name_of_form_element) }}
</div>
For rendering a select or option box manually check this link:
https://symfonycasts.com
i want to delete an advert without going to /delete/{id} path and just deleting with a modal pop-in.
In the dev environment, no problem , my form validation works great like that :
form.html.twig :
<div class="well">
{# form_start(form, {'attr': {'class': ''}}) #}
<form name="monext_perfclientbundle_advert" method="post" action="" class="" enctype="multipart/form-data">
{# Les erreurs générales du formulaire. #}
{{ form_errors(form) }}
<div class="form-group">
{# Génération du label. #}
{{ form_label(form.title, "Titre de l'annonce", {'label_attr': {'class': 'col-sm-3 control-label'}}) }}
{# Affichage des erreurs pour ce champ précis. #}
{{ form_errors(form.title) }}
<div class="col-sm-4">
{# Génération de l'input. #}
{{ form_widget(form.title, {'attr': {'class': 'form-control'}}) }}
</div>
</div>
<div class="form-group">
{{ form_label(form.content, "Contenu de l'annonce", {'label_attr': {'class': 'col-sm-3 control-label'}}) }}
{{ form_errors(form.content) }}
<div class="col-sm-4">
{{ form_widget(form.content, {'attr': {'class': 'ckeditor'}}) }}
</div>
</div>
{{ form_row(form.category) }}
<button id="addFile">Ajouter un fichier</button>
<div id="uploads"></div><br>
{{ form_widget(form.save, {'attr': {'class': 'btn btn-primary'}}) }}
{{ form_rest(form) }}
{{ form_end(form) }}
</form>
info.html.twig:
<div class="modal-footer parente">
<div>Annuler</div>
<div>
<form class="nomargin" action="{{ path('info_delete', {'id': advert.id}) }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
<input type="submit" value="Supprimer" class="btn btn-danger"/>{{ form_rest(form) }}
</form>
</div>
</div>
deleteAction() :
$form = $this->createFormBuilder()->getForm();
if ($form->handleRequest($request)->isValid()) {
$em->remove($advert);
$em->flush();
$request->getSession()->getFlashBag()->add('info', "L'annonce a bien été supprimée.");
return $this->redirect($this->generateUrl('info'));
}
return $this->render('MonextPerfclientBundle:Default:delete.html.twig', array(
'advert' => $advert,
'form' => $form->createView()
));
It doesnt work in production environment i dont know why..
my dump :
The CSRF token is invalid. Please try to resubmit the form
i got it thanks to Luax my friend !
{{ form_start(form, {'action': path('info_delete', {'id': advert.id})}) }}
<input type="hidden" name="form[_token]" value="{{ csrf_token('form') }}">
<input type="submit" value="Supprimer" class="btn btn-danger"/>{{ form_rest(form) }}
{{ form_end(form) }}
Issue resolved :)
How can I change class for expanded choice type label?
Default class is "required", but I need to change it to my own class.
How can I do this?
Thanks
You should render your form field yourself in your twig template like this:
<div class="form-group">
{{ form_label(form.expandedField) }}
<div class="col-md-10">
{% for child in form.expandedField.children %}
<div class="radio">
<label class="expanded" for="{{ child.vars.id }}">
{{ form_widget(child) }}
{{ child.vars.label }}
</label>
</div>
{% endfor %}
</div>
</div>
Every form element has a children attribute which is used for any child elements. In your case your radio buttons. Iterate over them and generate you label for every element with all those classes you need yourself.
I have a contacts form with two collections: functions and comments.
The comments collection is very standard and doesn't require any tweaks (just text field and file upload).
But the functions requires to override collection-item because I render each function in a tab.
My issue is that when I customize collection_item widget for the functions, it also tries to apply to the prototype of the comments collection. It fails as the fields are obviously different.
How can I manage that by for example forcing the comments collection to use the standard collection_item widget? Or maybe by passing a variable to the collection_widget block so that it behaves differently depending if it applies to functions or comments...
--EDIT: add twig templates--
Here is my main edit form :
{% extends 'contactsBundle:templates:edit.html.twig' %}
{% form_theme edit_form 'contactsBundle:forms:fonctions.html.twig' %}
{% block form_body -%}
<div class="row">
<div class="col-md-5">
{{ form_row(edit_form.prefix) }}
{{ form_row(edit_form.nom) }}
{{ form_row(edit_form.prenom) }}
</div>
<div class="col-md-5 col-md-offset-2">
{{ form_row(edit_form.referent) }}
{{ form_row(edit_form.groupe) }}
</div>
</div>
{{ form_label(edit_form.fonctions) }}
{{ form_errors(edit_form.fonctions, {attr: {class: 'fonctions-label'}}) }}
{{ form_widget(edit_form.fonctions, {attr: {class: 'fonctions-widget'}}) }}
<ul class="nav nav-tabs">
</ul>
<div class="tab-content">
{% for fonction in edit_form.fonctions %}
{% include 'contactsBundle:forms:fonctions-prototype.html.twig' with {form: fonction.vars.form, index: loop.index} %}
{% endfor %}
</div>
<div class="row">
<div id="commentaire_prototype">
data-prototype="{{ form_widget(edit_form.commentaires.vars.prototype) | e }}"
</div>
{% for commentaire in edit_form.commentaires %}
{{ form_row(commentaires.commentaire) }}
{{ form_row(commentaires.docFile) }}
{% endfor %}
</div>
{% endblock form_body %}
{% block body_end_before_js %}
{{ parent() }}
<script src="{{ asset('bundles/mopabootstrap/js/mopabootstrap-collection.js') }}"></script>
<script src="{{ asset('bundles/contacts/js/forms.js') }}"></script>
{% endblock body_end_before_js %}
Here is my customized collection_widget
{% extends 'contactsBundle:templates:edit.html.twig' %}
{% form_theme edit_form 'contactsBundle:forms:fonctions.html.twig' %}
{% block form_body -%}
<div class="row">
<div class="col-md-5">
{{ form_row(edit_form.prefix) }}
{{ form_row(edit_form.nom) }}
{{ form_row(edit_form.prenom) }}
</div>
<div class="col-md-5 col-md-offset-2">
{{ form_row(edit_form.referent) }}
{{ form_row(edit_form.groupe) }}
</div>
</div>
{{ form_label(edit_form.fonctions) }}
{{ form_errors(edit_form.fonctions, {attr: {class: 'fonctions-label'}}) }}
{{ form_widget(edit_form.fonctions, {attr: {class: 'fonctions-widget'}}) }}
<ul class="nav nav-tabs">
</ul>
<div class="tab-content">
{% for fonction in edit_form.fonctions %}
{% include 'contactsBundle:forms:fonctions-prototype.html.twig' with {form: fonction.vars.form, index: loop.index} %}
{% endfor %}
</div>
<div class="row">
<div id="commentaire_prototype">
{#data-prototype="{{ form_widget(edit_form.commentaires.vars.prototype) | e }}"#}
</div>
{#{{ form_row(edit_form.commentaires) }}#}
{% for commentaire in edit_form.commentaires %}
{{ form_row(commentaires.commentaire) }}
{{ form_row(commentaires.docFile) }}
{% endfor %}
</div>
{% endblock form_body %}
{% block body_end_before_js %}
{{ parent() }}
<script src="{{ asset('bundles/mopabootstrap/js/mopabootstrap-collection.js') }}"></script>
<script src="{{ asset('bundles/contacts/js/forms.js') }}"></script>
{% endblock body_end_before_js %}
And here is my fonctions.prototype.html.twig:
{% if index is not defined %}
{% set index = "__name__" %}
{% endif %}
<div class="collection-item tab-pane" id="{{ index }}">
<div class="row">
<div class="col-md-5">
{{ form_row(form.fonction, {'attr': {'class': 'fonction'} } ) }}
{{ form_row(form.titre) }}
{{ form_row(form.entite, {'attr': {'class': 'entite'} }) }}
{#Todo Add entity address#}
</div>
<div class="col-md-5 col-md-offset-2">
{% if index is defined %}
<div class="form-group">
<a class="btn btn-xs btn-danger coll-del" href="#">
<span class="glyphicon glyphicon-trash"></span>
Supprimer cette Fonction
</a>
</div>
{% else %}
<div class="form-group">
<a class="btn btn-xs btn-danger coll-del" data-collection-remove-btn=".curuba_contactsbundle_contacts_fonction___name___form_group" href="#">
<span class="glyphicon glyphicon-trash"></span>
Supprimer cette Fonction
</a>
</div>
{% endif %}
</div>
</div>
<div class="row">
<div class="col-md-5">
<h4>Contact Professionel</h4>
{{ form_row(form.persoFixe) }}
{{ form_row(form.persoMobile) }}
{{ form_row(form.persoFax) }}
{{ form_row(form.persoMail) }}
</div>
<div class="col-md-5 col-md-offset-2">
<h4>Secrétariat</h4>
{{ form_row(form.assFixe) }}
{{ form_row(form.assMobile) }}
{{ form_row(form.assFax) }}
{{ form_row(form.assMail) }}
</div>
</div>
</div>
Source: http://symfony.com/doc/current/cookbook/form/create_custom_field_type.html
I would go on about this as follows:
Create two form types (Bundle\Form\Type\FunctionType and Bundle\Form\Type\CommentType)
Note down the return value of getName() for each and register your new form types as services, for the following I assume curuba_comment and curuba_function:
#services.yml
services:
bundle.form.type.function:
class: Bundle\Form\Type\FunctionType
tags:
- { name: form.type, alias: curuba_function }
bundle.form.type.comment:
class: Bundle\Form\Type\CommentType
tags:
- { name: form.type, alias: curuba_comment }
Now in your form theme you can add the blocks curuba_comment_widget and curubu_function_widget in which you can call other blocks, e.g. collection_widget.
Then in your Forms Form type do ->add('somefield', 'comment')
Here is how I managed it in a simple way thanks to this post:
symfony2 multiple nested forms prototype
First I change the prototype_name for each collection :
$builder
->add('prefix')
->add('nom')
->add('prenom')
->add('referent')
->add('groupe')
->add('fonctions', 'collection', array(
'type' => new fonctionsType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'label' => 'Fonctions',
'label_attr' => array('class'=>'sub-form-label'),
'prototype_name'=> '__fon_prot__'
))
->add('commentaires', 'collection', array(
'type' => new commentairesType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'label' => 'Commentaires',
'prototype' => true,
'prototype_name'=> '__com_prot__'
))
->add('submit', 'submit', array('label' => 'Enregistrer', 'attr' => array('class' => 'btn btn-lg btn-success')))
Then I add an if statment in my collection_widget :
{% if prototype.vars.name == '__fon_prot__' %}
{% set prototype_markup = include('contactsBundle:forms:fonctions-prototype.html.twig', { 'form': form.vars.form.vars.prototype }) %}
{% else %}
{% set prototype_markup = form_row(prototype) %}
{% endif %}
And that's it.