Symfony2 form refresh same page after submit - forms

I have a form whose content is created from a DB.
in my controller i have:
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, $projectID)
{
//here I get all the data from DB and create the form
if ($form->isValid())
{
//here I do all the relevant changes in the DB
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
It updates the info on the DB properly, but it does not build again the form with updated data. Instead of the return inside the "isValid()" I simply need a refresh on the current page.
I assume it's possible and easy to accomplish, but I failed to find how to do it :/
EDIT - here comes more relevant code:
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, $projectID)
{
$user = $this->container->get('security.context')->getToken()->getUser(); //get current user
$em = $this->getDoctrine()->getManager(); //connect to DB
$prj = $this->getDoctrine()->getRepository('AppBundle:Project')->findOneById($projectID);
[...]
// here comes some code to generate the list of $HRsInThisProject and the list of roles ($rolesListForForm)
[...]
foreach ($HRsInThisProject as $key => $HR)
{
$form->add('roleOf_'.$key, 'choice', array('choices' => $rolesListForForm, 'required' => true, 'data' => $HR['role'], 'label' => false, ));
$form->add('isActive_'.$key, 'choice', array('choices' => [0 => 'Inactive', 1 => 'Active'] , 'required' => true, 'data' => $HR['is_active'], 'label' => false, ));
}
[...]
// here there is some code to get the $HRsInMyDomainForForm
[...]
$form->add('HRid', 'choice', array('choices' => $HRsInMyDomainForForm,'required' => false, 'placeholder' => 'Choose a resource', 'label' => false, ));
$form->add('role', 'choice', array('choices' => $rolesListForForm,'required' => false, 'placeholder' => 'Choose a role', 'label' => false, ));
$form->add('save', 'submit', array('label' => 'Save'));
$form->handleRequest($request);
if ($form->isValid())
{
{
[...] here there is a huge portion of code that determines if I need to generate a new "event" to be stored, or even multiple events as I can change several form fields at once
// If I needed to create the event I persist it (this is inside a foreach)
$em->persist($newHREvent);
}
$em->flush();
return $this->render('HR/show.html.twig', array('projectID' => $prj->getId(), 'hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
return $this->render('HR/show.html.twig', array('projectID' => $prj->getId(), 'hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
I also include a screenshot of the form:
If a user selects to add a new resouce, I need to persist it to DB (and that is done properly) but then I need to see it in the list of available HRs, without the need for the user to reload the page.

More dynamic way would be:
$request = $this->getRequest();
return $this->redirectToRoute($request->get('_route'), $request->query->all());
or simply
return $this->redirect($request->getUri());

I managed to solve it in a simple (and I hope correct) way.
I simply substituted the "render" inside the isValid() with the following:
return $this->redirect($this->generateUrl('hr_manage', array('projectID' => $prj->getId())));
I works, but does anybody foresee problems with this solution?

You have to link the form to the request.
$entity = new Entity();
$form = $this->createFormBuilder($entity)
->add('field1', 'text')
->add('field2', 'date')
->add('save', 'submit', array('label' => 'Submit'))
->getForm();
$form->handleRequest($request); // <= this links the form to the request.
only after that you test $form->isValid() and pass this form when rendering the template. If you already did this and haven't included in the code above please show more code for better help.

Here is the right way to do it. Event though you have $projectId slug, in Action you can pass whole Object, in this case Project. Symfony will take care for the rest (fetching right Project entity for you.
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, Project $project)
{
$form = $this->createForm(new ProjectType(), $project);
$form->handleRequest($request);
// ... your business logic or what ever
//here I get all the data from DB and create the form
if ($form->isValid() && $form->isSubmitted()) {
$em->persist($project);
// no need to flush since entity already exists
// no need to redirect
}
// here $form->createView() will populate fields with data since you have passed Poroject $project to form
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
Update
According to your edit, you need to use javascript for client-side dom manipulation. Check this link from Symfony official document embedded forms. Here you'll find an example of what you're trying to accomplish.

Related

Strange exception - Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed

I have this exception, in a strange behavior that I can't understand. I'll try to explain.
I have a form, where I can add create a report. The use can upload multiple attached pdf and a text comment. The form have 2 submit button, 'save' and 'saveAndClose'.
class ReportType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('documentDatas', CollectionType::class, array(
'entry_type' => DocumentType::class,
'entry_options' => ['data_class' => 'AppBundle\Model\DocumentPdfData', 'add_class' => 'upload-pdf'],
'allow_add' => true,
'allow_delete' => true,
'label' => false
))
->add('comment', CKEditorType::class, array(
'config' => array('toolbar' => 'my_toolbar'),
'label' => false,
'required' => false,
'input_sync' => true
))
->add('save', SubmitType::class, array('attr' => array('class' => 'btn btn-success mr-2')))
->add('saveAndClose', SubmitType::class, array('label' => 'saveAndClose', 'attr' => array('class' => 'btn btn-success float-right')))
;
}
}
The Save only persist the form, the saveAndClose obviously close the report, so user can't modify it anymore.
The exception
Serialization of 'Symfony\Component\HttpFoundation\File\File' is not allowed
appear when an user upload an attached and saveAndClose the form. Only in this case, other case works well (also upload attached, push save, return the the form and saveAndClose).
This is my controller:
if ($form->isSubmitted() && $form->isValid()) {
if ($form->getClickedButton() && 'saveAndClose' === $form->getClickedButton()->getName()) {
$this->get(ConfirmReport::class)->confirm($report, $user);
$em->flush();
$report->modify($reportData, $user);
$em->persist($report->getReportParameters());
$em->persist($report);
$em->flush();
$this->addFlash('success', $this->get('translator')->trans('ReportConfirmed'));
return $this->redirectToRoute('practitioner_visit_detail_to_do');
}
if ($form->getClickedButton() && 'save' === $form->getClickedButton()->getName()) {
$report->modify($ReportData, $user);
$em->persist($report->getReportParameters());
$em->persist($report);
$em->flush();
$this->addFlash('success', $this->get('translator')->trans('ReportSaved'));
return $this->redirectToRoute('practitioner_visit_detail_to_do');
}
}
So, the only difference between 2 flux is the confimReport service. Inside this I put a bool parameter of report to true and make some operation on the DB, to remove some read and write permission of the user on this report. Nothing about the file uploaded or something else. So, i can't understand what cause the exception.
N.B.:
If i comment the confirmReport service all work well (dont know why);
I obtain the exception but the entity manager is flushed, so in my db I have saved the operation of the user (also the file uploaded).
So then what else could cause this?
Maybe the second flushing messes up with the code ? Can you try this :
if ($form->isSubmitted() && $form->isValid() && $form->getClickedButton()) {
if ('saveAndClose' === $form->getClickedButton()->getName()) {
$this->get(ConfirmReport::class)->confirm($report, $user);
$msg='ReportConfirmed';
}
if ('save' === $form->getClickedButton()->getName()) {
$msg = 'ReportSaved';
}
$report->modify($ReportData, $user);
$em->persist($report->getReportParameters());
$em->persist($report);
$em->flush();
$this->addFlash('success', $this->get('translator')->trans($msg));
return $this->redirectToRoute('practitioner_visit_detail_to_do');
}
Can you also show the content of the confirm() function ?
Thanks

Not to validate the form in Symfony 2

Here is my form, I build in the controller:
$defaulData = ....
$formBuilder = $this->createFormBuilder($defaultData);
$entity_options = array(
'class' => 'MyBundle:Param',
'property' => 'description',
'query_builder' => function(EntityRepository $er) {
return $er->getParamsFromCategorieQueryBuilder(MyController::$category_for_list);
},
'label' => 'Donnée à afficher'
);
$formBuilder
->add('entity_types', 'entity', $entity_options);
The form is a list of Param objects, it displays good but for some reason, when I submit the form, I have an error on entity_types field saying that the value cannot be blank though there is one Param selected (even by default).
So I was wondering if I could disable validation.
When whould I put this validation_groups to false ? if it is in $entity_options, I tried it already and it does not work.
ty
You should modify you options like this (both require and groups are needed):
$entity_options = array(
'class' => 'MyBundle:Param',
'property' => 'description',
'query_builder' => function(EntityRepository $er) {
return $er->getParamsFromCategorieQueryBuilder(MyController::$category_for_list);
},
'required' => false,
'validation_groups' => false,
'label' => 'Donnée à afficher'
);
If the error is instead on the Form class itself, you should change in:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => false,
));
}
The way to prevent validation for good is this one :
$formBuilder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
$event->stopPropagation();
}, 900);
It prevents from calling the validation event.
The solution that giosh94mhz gave me what not good because even with validation_group = false some validation are still done.

how to set value from database in Zend Framework 1 in add form element

I have a form in Zend Framework 1. when I click on edit button I want to display values from databases in the form. but I don't know how to do it.
This is my form code:
// Add an email element
$this->addElement('text', 'orgname', array(
'required' => true,
'filters' => array('StringTrim'),
'style' => array('width:220px'),
'decorators'=>Array(
'ViewHelper','Errors'
)
));
This is my controller:
public function editclientcompanyAction()
$form = new Application_Form_Companyform();
$form->addform();
$this->view->form = $form;
$request = $this->getRequest();
$editid=$request->getParam('id');
$edit_show = new Application_Model_Clientcompany;
$showdetails = $edit_show->editclient($editid);
$this->view->assign('datas', $showdetails);
How do I display database vlaues in my Zend Form?
There are two cases.
1) Populating form which has fields same like the database table fields : If you have the form which has same fields like the database fields, then you can populate them easily.
First you need to get the data from the database and then call the Zend_Form populate function passing the data as an associative array, where keys will be same like form fields names and values will be values for the form fields, as below in case of your form.
This will be in your controller
$data = array("orgname" => "Value for the field");
$form = new Application_Form_Companyform();
$form->populate($data);
Now send will automatically populate the form field orgname. You dont need to modify your form or set the value field in the addElement.
*2)Setting field value manually: * The second case is to set the value manually. First you will need to modify your form and add a constructor to it. Also in your form class you will need to create a property (if you have multiple fields, then you can create an array property or multiple properties for each field. This will be all up to you.). And then set the value key in the addElement. Your form should look like this
class Application_Form_Companyform extends Zend_Form
{
private $orgname;
public function __contruct($orgname)
{
$this->orgname = $orgname;
//It is required to call the parent contructor, else the form will not work
parent::__contruct();
}
public function init()
{
$this->addElement('text', 'orgname',
array(
'required' => true,
'filters' => array('StringTrim'),
'style' => array('width:220px'),
'decorators'=>Array('ViewHelper','Errors'),
'value'=>$this->orgname
)
));
} //end of init
} //end of form
Now your controller, you will need to instantiate the form object passing the value of the orgname field like below
$form = new Application_Form_Companyform("This is the value for orgname");
And thats it.
I used such methods and it works like a charm. For your requirements, you may need to adjust the above sample code, as i did not checked it, but it will run fine for sure i hope :P
Thank you
Ok in either ZF1 or ZF2 just do this.
// Add an email element
$this->addElement('text', 'orgname',
array(
'required' => true,
'filters' => array('StringTrim'),
'style' => array('width:220px'),
'decorators' => Array('ViewHelper','Errors'),
'value' => $showdetails->orgname
)
));
You might want to test first for null/empty values first though, you could use ternary operators for convenience:
// Add an email element
$this->addElement('text', 'orgname',
array(
'required' => true,
'filters' => array('StringTrim'),
'style' => array('width:220px'),
'decorators' => Array('ViewHelper','Errors'),
'value' => empty($showdetails->orgname)? null : $showdetails->orgname
)
));
Please have a look in my edit function at /var/www/html/zend1app/application/controllers/CountryController.php :
public function editAction() {
$data = $this->getRequest()->getParams();
$id = (int)$data['id'];
$options = array();
$country = $this->getCountryModel()->fetchRow("id=$id");
if(!$country)
{
throw new Exception("Invalid Request Id!");
}
$form = new Application_Form_Country();
$form->addIdElement();
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost())){
$data = new Application_Model_Country();
if($data->save($form->getValues()))
{
$message = array("sucess" => "Country has been updated!");
}
else {
$message = array("danger" => "Country could not be updated!");
}
$this->_helper->FlashMessenger->addMessage($message);
return $this->_helper->redirector('index');
}
}
$options = array (
'id' => $country->id,
'name' => $country->name,
'code' => $country->code
);
$form->populate( $options ); // data binding in the edit form
$this->view->form = $form;
}
and form class at /var/www/html/zend1app/application/forms/Country.php :
class Application_Form_Country extends Zend_Form
{
public function init()
{
// Set the method for the display form to POST
$this->setMethod('post');
// Add an email element
$this->addElement('text', 'name', array(
'label' => 'Enter Country Name:',
'required' => true,
'filters' => array('StringTrim'),
'validators' => array(
array('validator' => 'StringLength', 'options' => array(0, 20))
)
));
// Add the comment element
$this->addElement('text', 'code', array(
'label' => 'Enter Country Code:',
'required' => true,
'validators' => array(
array('validator' => 'StringLength', 'options' => array(0, 20))
)
));
// Add the submit button
$this->addElement('submit', 'submit', array(
'ignore' => true,
'label' => 'Save',
));
// And finally add some CSRF protection
$this->addElement('hash', 'csrf', array(
'ignore' => true,
));
}
public function addIdElement()
{
$this->addElement('hidden', 'id');
}
}
HTH

Magento, add and set a checkbox on grid and form backend

I've a fully working backend page with a grid and a corresponding form to edit the changes on the corresponding model. I added a new field on the table, bit type, as it will answer to a yes/no configuration option from the user. I added the checkbox on both grid and form.
My problem is that after a couple of hours of searching and trying different approaches I can not set the checkbox checked value both on the grid and the form reading the corresponding field from the database. Also when I click on save on the form the value corresponding to the checkbox is always saved with 1. Everything else on the grid and the form works as it should. I have read here, here, here, here and some more sites and SO questions/answers but still no clue on what I'm doing wrong. Some solutions recommend using a combo box with YES/NO options, but I want a checkbox, can't be so difficult.
Grid code inside the function _prepareColumns():
protected function _prepareColumns() {
...
$this->addColumn('banner_gral', array(
'header' => Mage::helper('banners')->__('General'),
'align' => 'center',
'index' => 'banner_gral',
'type' => 'checkbox',
'values' => $this->getBannerGral()==1 ? 'true' : 'false',
));
...
}
public function __construct()
{
parent::__construct();
$this->setId('bannersgrid');
$this->setDefaultSort('bannerid');
$this->setDefaultDir('asc');
$this->setSaveParametersInSession(true);
$this->setUseAjax(true);
}
public function getGridUrl()
{
return $this->getUrl('*/*/grid', array('_current'=>true));
}
protected function _prepareCollection()
{
$collection = Mage::getModel('banners/bannersadmin')->getCollection();
$this->setCollection($collection);
return parent::_prepareCollection();
}
Form code to add the checkbox inside the function _prepareForm():
protected function _prepareForm()
{
$id = $this->getRequest()->getParam('id');
$params = array('id' => $this->getRequest()->getParam('id'));
if (Mage::registry('banners_data')->getdata()) {
$data = Mage::registry('banners_data')->getdata();
}
elseif (Mage::getSingleton('adminhtml/session')) {
$data = Mage::getSingleton('adminhtml/session')->getdata();
Mage::getSingleton('adminhtml/session')->getdata(null);
}
else {
$data = array();
}
$form = new Varien_Data_Form(array(
'id' => 'edit_form',
'action' => $this->getUrl('*/*/save', $params),
'method' => 'post',
'enctype' => 'multipart/form-data',
));
...
$fieldset->addField('banner_gral', 'checkbox', array(
'label' => Mage::helper('banners')->__('Is general'),
'name' => 'banner_gral',
'class' => 'banner_gral',
'checked' => $this->getBannerGral()==1 ? 'true' : 'false',
'onclick' => 'this.value == this.checked ? 1 : 0',
'note' => Mage::helper('banners')->__('blablablabla'),
'tabindex' => 2
));
...
}
On the saveAction() of my form I have:
$campaign->setbanner_gral(!empty($data['banner_gral']));
In your controller saveAction() when saving the checkbox data do
$banner_gral = isset($your_form_Data['banner_gral']) ? 1 : 0;
For Grid and Form Page
In your controller you should have Mage::register(...)->getData() or Mage::register(...)
public function editAction()
....
Mage::register('example_data', $model);
On your form _prepareForm()
$model = Mage::registry('example_data'); // NOTE registry('example_data'); NOT registry('example_data')->getData();
$fieldset->addField('entire_range', 'checkbox', array(
....
'checked' => $model->getBannerGral()==1 ? 'true' : 'false',
......
))
see http://www.magentocommerce.com/boards/viewthread/20536/
On your grid _prepareColumns()
$this->addColumn('banner_gral', array(
....
'type' => 'checkbox',
'index' => 'banner_gral',
'values' => array(1,2),
'field_name' => 'checkbox_name',
....
));
#R.S answered one issue, how to save the checkbox value on the corresponding model/database field. But the issue on how to correctly display the checkbox on both the grid and the form was not solved. After doing some more searches I finally got to these two links that helped me solve my problem.
To correct the grid issue: Understanding the Grid Serializer Block
Now the part of code where the checkbox column is added, see that I added array(1,2) on the values element.
$this->addColumn('banner_gral', array(
'header' => Mage::helper('banners')->__('General'),
'width' => '20px',
'type' => 'checkbox',
'align' => 'center',
'index' => 'banner_gral',
'values' => array(1,2),
'editable' => 'false',
));
Also if you take a look into the core code of Magento, the class Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Checkbox returns an array of values. Taking a look here finally got me into the right path.
/**
* Returns values of the column
*
* #return array
*/
public function getValues()
{
if (is_null($this->_values)) {
$this->_values = $this->getColumn()->getData('values') ? $this->getColumn()->getData('values') : array();
}
return $this->_values;
}
To correct the form issue: Mage_Adminhtml_Block_System_Store_Edit_Form Class Reference
The issue on this case was that I was trying to use the $this but what I needed to use was the $data that is loaded at the beginning of the _prepareForm function. #R.S pointed the right direction, but it is not possible to use $model->getBannerGral() as the $data on the registry is an array, not a model. So, using $data["banner_gral"] I could get the needed value for the checkbox. Tested and it is working.
$fieldset->addField('banner_gral', 'checkbox', array(
'label' => Mage::helper('banners')->__('Is general'),
'name' => 'banner_gral',
'checked' => $data["banner_gral"],
'onclick' => 'this.value = this.checked ? 1 : 0;',
'note' => Mage::helper('banners')->__('blablablabla'),
'tabindex' => 2
));

Symfony2 Setting a default choice field selection

I am creating a form in the following manner:
$form = $this->createFormBuilder($breed)
->add('species', 'entity', array(
'class' => 'BFPEduBundle:Item',
'property' => 'name',
'query_builder' => function(ItemRepository $er){
return $er->createQueryBuilder('i')
->where("i.type = 'species'")
->orderBy('i.name', 'ASC');
}))
->add('breed', 'text', array('required'=>true))
->add('size', 'textarea', array('required' => false))
->getForm()
How can I set a default value for the species listbox?
Thank you for your response, I apologise, I think I should rephrase my question. Once I have a value that I retrieve from the model, how do I set that value as SELECTED="yes" for the corresponding value in the species choice list?
So, that select option output from the TWIG view would appear like so:
<option value="174" selected="yes">Dog</option>
You can define the default value from the 'data' attribute. This is part of the Abstract "field" type (http://symfony.com/doc/2.0/reference/forms/types/field.html)
$form = $this->createFormBuilder()
->add('status', 'choice', array(
'choices' => array(
0 => 'Published',
1 => 'Draft'
),
'data' => 1
))
->getForm();
In this example, 'Draft' would be set as the default selected value.
If you use Cristian's solution, you'll need to inject the EntityManager into your FormType class. Here is a simplified example:
class EntityType extends AbstractType{
public function __construct($em) {
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options){
$builder
->add('MyEntity', 'entity', array(
'class' => 'AcmeDemoBundle:Entity',
'property' => 'name',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('e')
->orderBy('e.name', 'ASC');
},
'data' => $this->em->getReference("AcmeDemoBundle:Entity", 3)
));
}
}
And your controller:
// ...
$form = $this->createForm(new EntityType($this->getDoctrine()->getManager()), $entity);
// ...
From Doctrine Docs:
The method EntityManager#getReference($entityName, $identifier) lets you obtain a reference to an entity for which the identifier is known, without loading that entity from the database. This is useful, for example, as a performance enhancement, when you want to establish an association to an entity for which you have the identifier.
the solution: for type entity use option "data" but value is a object. ie:
$em = $this->getDoctrine()->getEntityManager();
->add('sucursal', 'entity', array
(
'class' => 'TestGeneralBundle:Sucursal',
'property'=>'descripcion',
'label' => 'Sucursal',
'required' => false,
'data'=>$em->getReference("TestGeneralBundle:Sucursal",3)
))
I think you should simply use $breed->setSpecies($species), for instance in my form I have:
$m = new Member();
$m->setBirthDate(new \DateTime);
$form = $this->createForm(new MemberType, $m);
and that sets my default selection to the current date. Should work the same way for external entities...
If you want to pass in an array of Doctrine entities, try something like this (Symfony 3.0+):
protected $entities;
protected $selectedEntities;
public function __construct($entities = null, $selectedEntities = null)
{
$this->entities = $entities;
$this->selectedEntities = $selectedEntities;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('entities', 'entity', [
'class' => 'MyBundle:MyEntity',
'choices' => $this->entities,
'property' => 'id',
'multiple' => true,
'expanded' => true,
'data' => $this->selectedEntities,
]);
}
I don't think you should use the data option, because this does more than just setting a default value.
You're also overriding any data that's being passed to the form during creation. So basically, you're breaking
support for that feature. - Which might not matter when you're letting the user create data, but does matter when you
want to (someday) use the form for updating data.
See http://symfony.com/doc/current/reference/forms/types/choice.html#data
I believe it would be better to pass any default data during form creation. In the controller.
For example, you can pass in a class and define the default value in your class itself.
(when using the default Symfony\Bundle\FrameworkBundle\Controller\Controller)
$form = $this->createForm(AnimalType::class, [
'species' => 174 // this id might be substituted by an entity
]);
Or when using objects:
$dog = new Dog();
$dog->setSpecies(174); // this id might be substituted by an entity
$form = $this->createForm(AnimalType::class, $dog);
Even better when using a factory:
(where dog probably extends from animal)
$form = $this->createForm(AnimalType::class, DogFactory::create());
This will enable you to separate form structure and content from each other and make
your form reusable in more situations.
Or, use the preferred_choices option, but this has the side effect of moving the default option to the top of your form.
See: http://symfony.com/doc/current/reference/forms/types/choice.html#preferred-choices
$builder->add(
'species',
'entity',
[
'class' => 'BFPEduBundle:Item',
'property' => 'name',
'query_builder' => ...,
'preferred_choices' => [174] // this id might be substituted by an entity
]
);
I'm not sure what you are doing wrong here, when I build a form using form classes Symfony takes care of selecting the correct option in the list. Here's an example of one of my forms that works.
In the controller for the edit action:
$entity = $em->getRepository('FooBarBundle:CampaignEntity')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find CampaignEntity entity.');
}
$editForm = $this->createForm(new CampaignEntityType(), $entity);
$deleteForm = $this->createDeleteForm($id);
return $this->render('FooBarBundle:CampaignEntity:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
The campaign entity type class (src: Foo\BarBundle\Form\CampaignEntityType.php):
namespace Foo\BarBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Doctrine\ORM\EntityRepository;
class CampaignEntityType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('store', 'entity', array('class'=>'FooBarBundle:Store', 'property'=>'name', 'em'=>'my_non_default_em','required' => true, 'query_builder' => function(EntityRepository $er) {return $er->createQueryBuilder('s')->orderBy('s.name', 'ASC');}))
->add('reward');
}
public function getName()
{
return 'foo_barbundle_campaignentitytype';
}
}
From the docs:
public Form createNamed(string|FormTypeInterface $type, string $name, mixed $data = null, array $options = array())
mixed $data = null is the default options. So for example I have a field called status and I implemented it as so:
$default = array('Status' => 'pending');
$filter_form = $this->get('form.factory')->createNamedBuilder('filter', 'form', $default)
->add('Status', 'choice', array(
'choices' => array(
'' => 'Please Select...',
'rejected' => 'Rejected',
'incomplete' => 'Incomplete',
'pending' => 'Pending',
'approved' => 'Approved',
'validated' => 'Validated',
'processed' => 'Processed'
)
))->getForm();
Setting default choice for symfony2 radio button
$builder->add('range_options', 'choice', array(
'choices' => array('day'=>'Day', 'week'=>'Week', 'month'=>'Month'),
'data'=>'day', //set default value
'required'=>true,
'empty_data'=>null,
'multiple'=>false,
'expanded'=> true
))
The form should map the species->id value automatically to the selected entity select field. For example if your have a Breed entity that has a OnetoOne relationship with a Species entity in a join table called 'breed_species':
class Breed{
private $species;
/**
* #ORM\OneToOne(targetEntity="BreedSpecies", mappedBy="breed")
*/
private $breedSpecies;
public function getSpecies(){
return $breedSpecies->getSpecies();
}
private function getBreedSpecies(){
return $this->$breedSpecies;
}
}
The field 'species' in the form class should pick up the species->id value from the 'species' attribute object in the Breed class passed to the form.
Alternatively, you can explicitly set the value by explicitly passing the species entity into the form using SetData():
$breedForm = $this->createForm( new BreedForm(), $breed );
$species = $breed->getBreedSpecies()->getSpecies();
$breedForm->get('species')->setData( $species );
return $this->render( 'AcmeBundle:Computer:edit.html.twig'
, array( 'breed' => $breed
, 'breedForm' => $breedForm->createView()
)
);
You can either define the right default value into the model you want to edit with this form or you can specify an empty_data option so your code become:
$form = $this
->createFormBuilder($breed)
->add(
'species',
'entity',
array(
'class' => 'BFPEduBundle:Item',
'property' => 'name',
'empty_data' => 123,
'query_builder' => function(ItemRepository $er) {
return $er
->createQueryBuilder('i')
->where("i.type = 'species'")
->orderBy('i.name', 'ASC')
;
}
)
)
->add('breed', 'text', array('required'=>true))
->add('size', 'textarea', array('required' => false))
->getForm()
;
You can use "preferred_choices" and "push" the name you want to select to the top of the list. Then it will be selected by default.
'preferred_choices' => array(1), //1 is item number
entity Field Type