symfony2 formbuilder - symfony

i created a customFormtype in symfony2 and i'm using it in a formbuilder in my controller.
This is the html result when i render the form:
<div id="form">
<input type="hidden" id="form__token" name="form[_token]" value="2e8fe0d777b5c0d7d30d9bfd9d5143811c790b1d">
<div>
<label class=" required">Stars</label>
<!-- some other stuff -->
</div>
</div>
Where does the id form came from and where can i change the name?
Thank you very much.

The id of the form is defined by the getName() function
class TaskType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('task');
$builder->add('dueDate', null, array('widget' => 'single_text'));
}
public function getName()
{
return 'task';
}
}
Ex. 'task' here. (http://symfony.com/doc/current/book/forms.html#creating-form-classes)

You may use a named form builder:
protected function createMyForm()
{
return $this->container->get('form.factory')->createNamedBuilder('my_form_name', 'form')
->add('id', 'hidden')
->getForm();
}

Related

setting the name of an AbstractType in a contact form for PHPUnit

I'm trying to PHPUnit test a method for a contact form
public function testContact()
{
$client = static::createClient();
$form = $crawler->selectButton('Submit')->form();
$form['blogbundle_enquirytype[name]'] = 'name';
// other form field assignments here
$crawler = $client->submit($form);
$this->assertEquals(1, $crawler->filter('.blogger-notice:contains("Your contact enquiry was successfully sent. Thank you!")')->count());
}
PHPUnit doesn't recognize blogbundle_enquirytype (Unreachable field) presumably because the controller instantiates it like this
$enquiry = new Enquiry();
$form = $this->createForm(EnquiryType::class, $enquiry);
So despite the AbstractType:
class EnquiryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
$builder->add('email', EmailType::class);
$builder->add('subject');
$builder->add('body', TextareaType::class);
}
public function getName(){
return 'blogbundle_enquirytype';
}
Is there another way to set the name of the EnquiryType, or a way for Phpunit to identify the form?
Here is the form
<form action="/contact" method="post" class="blogger">
<div><label for="enquiry_name" class="required">Name</label><input type="text" id="enquiry_name" name="enquiry[name]" required="required" maxlength="255" /></div>
<div><label for="enquiry_email" class="required">Email</label><input type="email" id="enquiry_email" name="enquiry[email]" required="required" /></div>
<div><label for="enquiry_subject" class="required">Subject</label><input type="text" id="enquiry_subject" name="enquiry[subject]" required="required" maxlength="50" /></div>
<div><label for="enquiry_body" class="required">Body</label><textarea id="enquiry_body" name="enquiry[body]" required="required"></textarea></div>
<input type="hidden" id="enquiry__token" name="enquiry[_token]" value="-eZq7Go6ELXykluf0Fca_CPvzeB3yEUj2yuOnyamYBU" />
<input type="submit" value="Submit" />
</form>
Try this:
$form['enquiry[name]'] = 'name';
instead of:
$form['blogbundle_enquirytype[name]'] = 'name';
UPDATE:
Regarding to the migration guide to the symfony3:
The getBlockPrefix() method was added to the FormTypeInterface in
replacement of the getName() method which has been removed.
So you can continue to use your code of the testing class if you change the form method from this:
/**
* Returns the prefix of the template block name for this type.
*
* The block prefix defaults to the underscored short class name with
* the "Type" suffix removed (e.g. "UserProfileType" => "user_profile").
*
* #return string The prefix of the template block name
*/
public function getBlockPrefix(){
return 'blogbundle_enquirytype';
}
instead of this:
public function getName(){
return 'blogbundle_enquirytype';
}
Hope this help

Display Many-To-One fields in Symfony2 forms?

I am having two entity files one as Activite.php and another as Mesurage.php.
Now i want to display an Activite form with 3 fields typeActivite, emplacement and mesurage. the mesurage will be a selection that will fetch data from mesurage table. here is the code that i wrote inside Activite.php to create a many_to_one field for mesurage_id
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="GestionEnvironnementale\ISO14001Bundle\Entity\Mesurage")
*/
private $mesurage;
Below is my Form generation Code :
class ActiviteType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('typeActivite'),
->add('emplacement'),
->add('mesurage', 'entity', array('class' => 'ISO14001Bundle:Mesurage'));
}
}
here is my form code :
<div class="well">
<form method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<br/> <input type="submit" value="Envoyer" class="btn btn-primary" />
</form>
<script src="{{ asset('js/jquery-2.1.1.min.js') }}"></script>
<script type="text/javascript">
$(document).ready(function()
{
var $container3 = $('div#gestionenvironnementale_iso14001bundle_activitetype_activiteMesurage');
var $lienAjout3 = $('Ajouter un mesurage');
$container3.append($lienAjout3);
$lienAjout3.click(function(h) {
ajouterMesurage($container3);
h.preventDefault();
return false;
});
var index3 = $container3.find(':input').length;
if (index3 == 0) {
ajouterMesuragePolluant($container3);
} else {
$container3.children('div').each(function() {
ajouterLienSuppression3($(this));
});
}
function ajouterMesurage($container3) {
var $prototype3 = $($container3.attr('data-prototype').replace(/__name__label__/g, 'Mesurage n°' + (index3+1))
.replace(/__name__/g, index3));
ajouterLienSuppression3($prototype3);
$container3.append($prototype3);
index3++;
}
function ajouterLienSuppression3($prototype3) {
$lienSuppression3 = $('Supprimer');
$prototype3.append($lienSuppression3);
$lienSuppression3.click(function(h) {
$prototype3.remove();
h.preventDefault();
return false;
});
}
});
the code works very well but I dont want to display the list of Mesurage, I want to display the form of Mesurage to add a new !!
If you want to display a form even for mesurage, you have to take a look at embed form
So, basically, you have to create a FormType for mesurage (call it MesurageFormType) and modify your ActiviteType as follows
class ActiviteType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('typeActivite'),
->add('emplacement'),
->add('mesurage', 'collection', array(
'type' => new MesurageFormType(),
'allow_add' => true,));
}
}
This should be fine but if you want to render in a different way your form you should use prototype and jquery

Cannot generate one web form by attaching two entities to it

I have a 1 to n relationship so one Brand has many Cars. What I want to do is to create only one web form where all the fields from both of the entities get displayed. To do that I created a form type but I think I'm doing something wrong because I' getting error below when trying to print the form fields in twig. Could anyone tell me where am I doing wrong?
Error:
Method "brand" for object "Symfony\Component\Form\FormView" does not exist in CarBrandBundle:Default:both.html.twig at line 1
Entities:
class BrandEntity
{
protected $name;
protected $origin;
//Followed by getters and setters
/**
* #ORM\ManyToOne(targetEntity="BrandEntity", inversedBy="car")
* #ORM\JoinColumn(name="brand_id", referencedColumnName="id", nullable=false)
* #var object $brand
*/
protected $brand;
}
class CarEntity
{
protected $model;
protected $price;
//Followed by getters and setters
/**
* #ORM\OneToMany(targetEntity = "CarEntity", mappedBy = "brand")
* #var object $car
*/
protected $car;
public function __construct()
{
$this->car = new ArrayCollection();
}
public function addCar(\Car\BrandBundle\Entity\CarEntity $car)
{
$this->car[] = $car;
return $this;
}
public function removeCar(\Car\BrandBundle\Entity\CarEntity $car)
{
$this->car->removeElement($car);
}
}
Form Type:
namespace Car\BrandBundle\Form\Type;
use Car\BrandBundle\Entity\BrandEntity;
use Car\BrandBundle\Entity\CarEntity;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Test\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class BothType extends AbstractType
{
public function builder(FormBuilderInterface $builder, array $options)
{
$builder
->setAction($options['action'])
->setMethod('POST')
->add('brand', new BrandEntity())
->add('car', new CarEntity())
->add('button', 'submit', array('label' => 'Add'))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
//'data_class' => 'Car\BrandBundle\Entity\CarEntity',
'cascade_validation' => true
));
}
public function getName()
{
return 'both';
}
}
Controller:
namespace Car\BrandBundle\Controller;
use Car\BrandBundle\Form\Type\BothType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class BothController extends Controller
{
public function indexAction()
{
$form = $this->getFrom();
return $this->render('CarBrandBundle:Default:both.html.twig',
array('page' => 'Both', 'form' => $form->createView()));
}
private function getFrom()
{
return $this->createForm(new BothType(), null,
array('action' => $this->generateUrl('bothCreate')));
}
}
Twig:
{{ form_row(form.brand.name) }}
{{ form_row(form.brand.origin) }}
{{ form_row(form.car.model) }}
{{ form_row(form.car.price) }}
If you want a "car form" in which you need to choose a brand, then the other answer will be ok.
If what you want is a "brand form" in which you can add /edit/delete several cars, then you need to embed a Collection of Forms.
The cookbook answer is here: http://symfony.com/doc/current/cookbook/form/form_collections.html
To render a brand form containing a collection of car forms (1-n relationship):
The form types will look like this:
The brand type
// src/Acme/TaskBundle/Form/Type/BrandType.php
//...
class BrandType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('description');
$builder->add('cars', 'collection', array('type' => new CarType()));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\BrandBundle\Entity\Brand',
));
}
public function getName()
{
return 'brand';
}
}
The car type:
namespace Acme\CarBundle\Form\Car;
//...
class TagType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\CarBundle\Entity\Car',
));
}
public function getName()
{
return 'car';
}
}
Then the controller and the views just like in the cookbook. It's very powerful and easy in the end.
To add entities to a form you must use the entity field type: from the docs
$builder->add('users', 'entity', array(
'class' => 'AcmeHelloBundle:User',
'property' => 'username',
));
In this case, all User objects will be loaded from the database and rendered as either a select tag, a set or radio buttons or a series of checkboxes (this depends on the multiple and expanded values). If the entity object does not have a __toString() method the property option is needed.
Also please post the relationships.

Change name attribute of symfony 2 form field

I have a form to register :
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->add('tel');
$builder->add('telvisible');
}
after the display of this field:
<input type="checkbox" id="fos_user_registration_form_telvisible" name="fos_user_registration_form[telvisible]" value="1">
But I want to be displayed:
<input type="checkbox" id="fos_user_registration_form_telvisible" name="telvisible" value="1">
To remove type name from the name you have good two solutions:
Return null in your getName or getBlockPrefix implementation.
public function getBlockPrefix()
{
return null;
}
Create the form using createNamed method.
$form = $this->get('form.factory')
->createNamedBuilder(null, 'form', $address)
->add('address', 'text');

use multi entity in form builder in symfony2

i want to use more than one entity to create form in createformbuilder .
forexample i want to have a form with many fields from many entity
and i want to check condition for view fields
userEntity -> email , password
resselerEntity - > (userEntity fields) + managerName , managerFamily
leaderEntity - > (userEntity fields) + credit
and if i want to show resseler fields , must show all fields of userEntity and resselerEntity
if want to show userEntity , must show all fields of userEntity
and etc,
so how can i solve this solution ?
Thanks in advance!
Most common solution is to create single forms for (in your case):
userEntity
ressellerEntity
Then, create a new form that have two fields of userEntityFormType and ressellerEntityFormType.
In that way you can:
Separate your constraints
Use elsewhere single form
Something like that
class UserEntityType extends AbstractType
{
public function BuildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('firstField')
->add('secondField')
[...]
->lastField;
}
public function getName()
{
return 'UserEntityType ';
}
}
class RessellerEntityType extends AbstractType
{
public function BuildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('firstField')
->add('secondField')
[...]
->lastField;
}
public function getName()
{
return 'RessellersEntityType ';
}
}
class AggregateEntityType extends AbstractType
{
public function BuildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('userEntityField',UserEntityType,array('multiple'=>true)
->add('ressellersEntityField',RessellersEntityType,array('multiple'=>true));
}
public function getName()
{
return 'AggregateEntityType ';
}
}
I think Don got you most of the way there. Add a construct argument to your UserType
public function __construct($otherEntityType) // Reseller, Leader etc.
Then use otherEntityType to determine which fields are created for UserType.
As far as I understand your problem, you should use type inheritance:
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('password')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => '\Hamid\User',
));
}
public function getName()
{
return 'hamid_user';
}
}
class ResellerType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('managerName')
->add('managerFamily')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => '\Hamid\Reseller',
));
}
public function getName()
{
return 'hamid_reseller';
}
public function getParent()
{
return 'hamid_user';
}
}
Then use the right form for each entity. If, for whatever reason, you need a single form that adapts to the class of the entity set to the form, you need to use form events, as explained in the documentation.

Resources