I can't find how to update data in form collection to database, like in normal Edit action, the EditForm generated and pass to UpdateAction. I can make form for EditForm but can't find how to update data to database.
How to Embed a Collection of Forms is showing how to add and delete it using persist and remove but how to bind it from post data and update it into database? My collection actually just entity without table in database. It's used just for population many fields from my primary entity DftAbsensi into single form.
This is my primary entity DftAbsensi (without getter and setter):
<?php
namespace Sifo\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class DftAbsensi
{
private $id;
private $tanggal;
private $status;
This is the collection entity for Absensi :
<?php
namespace Sifo\AdminBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
class CollectionAbsensi
{
private $statusS;
private $tanggal;
public function __construct()
{
$this->tanggalS = new ArrayCollection();
$this->statusS = new ArrayCollection();
}
public function setTanggal($tanggal)
{
$this->tanggal = $tanggal;
return $this;
}
public function getTanggal()
{
return $this->tanggal;
}
public function setStatusS(ArrayCollection $statusS)
{
$this->statusS = $statusS;
return $this;
}
public function getStatusS()
{
return $this->statusS;
}
}
This is DftAbsensiType :
<?php
namespace Sifo\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class DftAbsensiType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', 'text', array('required' => false))
->add('status', 'choice', array(
'choices' => array('H' => 'Hadir', 'A' => 'Tanpa Keterangan', 'S' => 'Sakit', 'I' => 'Izin', 'L' => 'Libur'),
'required' => false,
'empty_value' => '- Pilih -'))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Sifo\AdminBundle\Entity\DftAbsensi'
));
}
public function getName()
{
return 'sifo_adminbundle_dftabsensi';
}
}
Actually I'm using collection just for populating many fields from databases. Persist database just in my primary entity DftAbsensi above. This is Collection for Absensi Type :
<?php
namespace Sifo\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CollectionAbsensiType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('tanggal', 'date', array('label' => false, 'required' => false, 'attr'=>array('style'=>'display:none;'), 'widget' => 'single_text', 'format' => 'yyyy-MM-dd'))
->add('statusS', 'collection', array(
'label' => false,
'options' => array('label' => false, 'required' => false),
'type' => new DftAbsensiType())
);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Sifo\AdminBundle\Entity\CollectionAbsensi'
));
}
public function getName()
{
return 'sifo_adminbundle_collectionabsensi';
}
}
This is how to population data in my controller. This form used for EditForm :
<?php
namespace Sifo\AdminBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sifo\AdminBundle\Entity\DftAbsensi;
use Sifo\AdminBundle\Entity\CollectionAbsensi;
use Sifo\AdminBundle\Form\CollectionAbsensiType;
use Sifo\AdminBundle\Form\DftAbsensiType;
/**
* DftAbsensi controller.
*
*/
class DftAbsensiController extends Controller
{
public function manageAction(Request $request, $id)
{
$user = $this->getUser();
$emGrupPelajar = $this->getDoctrine()->getManager();
$entityGrupPelajar = $emGrupPelajar->getRepository('SifoAdminBundle:DftGrupPelajar')->findByIdGrup($id);
/* check tanggal and set if exist */
$tanggal = $request->request->get('sifo_adminbundle_collectionabsensi')['tanggal'];
if($tanggal == NULL)
$tanggal = $request->request->get('form')['tanggal'];
$tanggal = new \DateTime($tanggal);
/* Show data */
$emShow = $this->getDoctrine()->getManager();
$collectionAbsensi = new CollectionAbsensi();
foreach ($entityGrupPelajar as $temp) {
$entity = new DftAbsensi();
$entity = $emShow->getRepository('SifoAdminBundle:DftAbsensi')->findOneBy(array('idGrupPelajar' => $temp, 'tanggal' => $tanggal));
if ($entity)
{
$entityPelajar = $emShow->getRepository('SifoAdminBundle:MstPelajar')->find($temp->getIdPelajar());
$dftAbsensi = new DftAbsensi();
$dftAbsensi->setId($entity->getId())
->setIdGrupPelajar($entity->getIdGrupPelajar())
->setStatus($entity->getStatus())
;
$collectionAbsensi->getStatusS()->add($dftAbsensi);
$collectionAbsensi->setTanggal($tanggal);
}
}
$emShow->flush();
$formEdit = $this->createForm(new CollectionAbsensiType(), $collectionAbsensi, array(
'action' => $this->generateUrl('admin_absensi_update', array('id' => $id)),
'method' => 'PUT',
));
$formEdit->add('save', 'submit', array('attr' => array('class' => 'btn btn-info')));
return $this->render('SifoAdminBundle:DftAbsensi:manage.html.twig', array(
'form_refresh' => $formRefresh->createView(),
'form_edit' => $formEdit->createView(),
'user' => $user,
));
}
As mentioned before, my CollectionAbsensi actually just used for population fields from databases. But for updating I'm using DftAbsensi Entity. There is no table for CollectionAbsensi in my databases. This is how I update the data:
public function updateAction(Request $request, $id)
{
$user = $this->getUser();
$emGrupPelajar = $this->getDoctrine()->getManager();
$entityGrupPelajar = $emGrupPelajar->getRepository('SifoAdminBundle:DftGrupPelajar')->findByIdGrup($id);
/* set tanggal */
$tanggal = new \DateTime($request->request->get('sifo_adminbundle_collectionabsensi')['tanggal']);
/* populate data */
$emShow = $this->getDoctrine()->getManager();
$collectionAbsensi = new CollectionAbsensi();
foreach ($entityGrupPelajar as $temp) {
$entity = new DftAbsensi();
$entity = $emShow->getRepository('SifoAdminBundle:DftAbsensi')->findOneBy(array('idGrupPelajar' => $temp, 'tanggal' => $tanggal));
if ($entity)
{
$entityPelajar = $emShow->getRepository('SifoAdminBundle:MstPelajar')->find($temp->getIdPelajar());
$dftAbsensi = new DftAbsensi();
$dftAbsensi->setId($entity->getId())
->setIdGrupPelajar($entity->getIdGrupPelajar())
->setStatus($entity->getStatus())
;
$collectionAbsensi->getStatusS()->add($dftAbsensi);
$collectionAbsensi->setTanggal($tanggal);
}
}
$formEdit = $this->createForm(new CollectionAbsensiType(), $collectionAbsensi);
$formEdit->handleRequest($request);
$emShow->flush();
$response = $this->forward('SifoAdminBundle:DftAbsensi:manage', array(
'id' => $id,
'request' => $request,
));
return $response;
}
There is no error from this code. The problem is the databases not updated when I press Save button. I confused for binding data and how to update them into database in updateAction above. Can a collection form not be used for updating data?
My form is attendance system which look like this :
Actually this is still not really answer my question about "How to update data in form collection?". I do update my data with old way : Get all the data from request manually and bind it to entity then update it into database.
Here my code :
public function updateAction(Request $request, $id)
{
$user = $this->getUser();
/* get request */
$data = $request->request->get('sifo_adminbundle_collectionabsensi')['statusS'];
/* update data */
$total = count($data);
for ($i = 0; $i < ($total / 2); $i++) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('SifoAdminBundle:DftAbsensi')->find($data[$i]['id']);
if ($entity){
$entity->setStatus($data[$i]['status'])
->setOperator($user->getNama());
$em->flush();
}
}
$response = $this->forward('SifoAdminBundle:DftAbsensi:manage', array(
'id' => $id,
'request' => $request,
));
return $response;
}
If someone has a better idea, post your answer here.
Related
First sorry for my english because is not great!
So I want to hide a field according to it's role because if I make with Twig the field to display on the bottom form
My code for understand, this's my LinkType :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('link')
->add('description')
// this field to hidden according the role
->add('published', CheckboxType::class);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Link'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_link';
}
a part of Controler:
public function newAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$categories = $em->getRepository('AppBundle:Category')->findAll();
$subCategories = $em->getRepository('AppBundle:SubCategory')->findAll();
$gestionCategorie = $this->container->get('app.categorie');
$link = new Link();
$repository = $this
->getDoctrine()
->getManager()
->getRepository('AppBundle:Link');
$category = $repository->findCategory();
$subCategory = $repository->findSubCategory();
$form = $this
->get('form.factory')
->create('AppBundle\Form\LinkType', $link)
->add('categories', ChoiceType::class, array(
// on inverse les clés et valeurs
'choices' => array_flip($category),
'label' => "Catégorie",
'attr' => ['class' => 'form-control'],
))
->add('sousCategories', ChoiceType::class, array(
// on inverse les clés et valeurs
'choices' => array_flip($subCategory),
'label' => "Sous-catégorie",
'attr' => ['class' => 'form-control'],
));
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
If you have other questions, don't hesitate
If you want to do this in the controller, first remove your field in your form class, then add:
$user = $this->getUser();
if (in_array('MY_ROLE_NAME', $user->getRoles())) {
$builder->add('published', CheckboxType::class);
}
A better and cleaner approach is using a form as a service and injecting token storage service into it:
// services.yml
AppBundle\Form\:
resource: '../../src/AppBundle/Form'
public: true
autowire: true
// Form type class
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
//...
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$user = $this->tokenStorage->getToken()->getUser();
$builder
->add('title')
->add('link')
->add('description');
if (in_array('MY_ROLE_NAME', $user->getRoles())) {
$builder->add('published', CheckboxType::class);
}
}
I'm new in php and symfony
I use a file service for the upload in symfony 2.8
I got 2 tables One Salon to many Files
I can upload multiple files in my newaction.
The problem happened at the editAction of my SalonController.
I would like to remove the older files in order to add newfiles in my editfiles.html.twig. And I tried a foreach in order to get this array...
Could you help me please ?
Here is the error
Type error: Argument 1 passed to DefaultBundle\Service\FileService::upload() must be an instance of DefaultBundle\Entity\File, instance of Doctrine\ORM\PersistentCollection given, called in /var/www/html/salon-beaute/src/SalonBundle/Controller/SalonController.php on line 131
And the stack trace focused on the line 18 of the fileservice.php
public function upload(File $file = null, $type) {
Here is the my newaction and editaction of my SalonController
class SalonController extends Controller
{
/**
* Creates a new salon entity.
*
* #Route("/new", name="salon_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$this->denyAccessUnlessGranted('ROLE_SALON');
$em = $this->getDoctrine()->getManager();
$salon = new Salon();
$options = array('role' => $this->getUser()->getRoles(), 'page' => 'add');
$form = $this->createForm( 'SalonBundle\Form\SalonType',$salon, $options);
$user = $this->getUser();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$uploadService = $this->get('app.file');
$myFiles = $form->get('file')->getData();
foreach($myFiles['path'] as $new_file) {
$file = new File();
$file->setPath($new_file);
$file->setSalon($salon);
$salon->addFile($file);
$uploadService->upload($file, 'salon');
$em->persist($file);
}
$user->setSalon($salon);
$salon->setEnable(false);
$em->persist($user);
$em->persist($salon);
$em->flush();
$this->get('email')->salon($salon);
return $this->redirectToRoute('salon_show', array('id' => $salon->getId()));
}
/**
* Displays a form to edit an existing salon entity.
*
* #Route("/edit", name="salon_edit")
* #Method({"GET", "POST"})
* #Security("has_role('ROLE_SALON')")
*/
public function editAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
$salon = $user->getSalon();
$deleteForm = $this->createDeleteForm($salon);
$options = array('role' => $this->getUser()->getRoles(), 'page' => 'edit');
$editForm = $this->createForm('SalonBundle\Form\SalonType', $salon, $options);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
// If new file
$edit_file = $editForm->get('edit_file')->getData();
if (!is_null($edit_file)) {
$file_current = $salon->getFiles();
$salon->getFiles($edit_file);
if (!$this->get('app.file')->upload($salon->getFiles(), 'salon'))
$salon->getFiles($file_current);
}
foreach($edit_file['path'] as $new_edit_file) {
$file = new File();
$file->setPath($new_edit_file);
$file->setSalon($salon);
$salon->addFile($file);
$this->get('app.file')->upload($file);
$em->persist($file);
}
$this->getDoctrine()->getManager()->flush();
$this->addFlash('success', 'Le partenaire a bien été modifié');
return $this->redirectToRoute('salon_show');
}
return $this->render('#Salon/salon/edit.html.twig', array(
'salon' => $salon,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
return $this->render('#Salon/salon/new.html.twig', array(
'salon' => $salon,
'form' => $form->createView(),
));
}
A portion of my SalonType
class SalonType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$page = $options['page'];
$builder
->add('name', TextType::class, array(
'label' => 'Nom du salon'
))
->add('content', TextareaType::class, array(
'label' => 'Descriptif'
))
->add('address_salon', AddressType::class, array(
'label' => ' '
))
;
if($page == 'add') {
$builder
->add('file', FileType::class, array(
'label' => 'Vous pouvez téléchargez jusqu\'à 3 images',
'required' => false,
'mapped' =>false,
));
}
if($page == 'edit') {
$builder
->add('edit_file', FileType::class, array(
'label' => 'Nouveau fichier',
'required' => false,
'mapped' => false
));
};
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'SalonBundle\Entity\Salon',
'role' => null
));
$resolver
->setRequired(['page']);
}
My fileType
class FileType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('path', \Symfony\Component\Form\Extension\Core\Type\FileType::class, array(
'label' => 'Image',
'multiple' => true,
))
;
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => null,
));
}
}
My fileService
<?php
namespace DefaultBundle\Service;
use DefaultBundle\Entity\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FileService {
private $directory_root;
private $directory_default;
public function __construct($directory_root, $directory_default) {
$this->directory_root = $directory_root;
$this->directory_default = $directory_default;
}
public function upload(File $file = null, $type) {
$path = $this->getDirectory($type);
if (is_null($file))
return false;
// Get file (Class UploadFile)
$file_uploaded = $file->getPath();
if ($file_uploaded->getError())
return false;
// Move file
$file_name = md5(uniqid()) . '.' . $file_uploaded->guessExtension();
$file_uploaded->move($this->directory_root . $path, $file_name);
// Update object file
$path .= '/' . $file_name;
$file->update($file_uploaded, $path);
return true;
}
public function delete(File $file){
$path = $this->directory_root.$file->getPath();
if(file_exists($path))
unlink($path);
}
private function getDirectory($type) {
switch ($type) {
default:
return $this->directory_default;
}
}
}
Your code is kinda messy, by that I mean you have lot of logic in your controller :-)
Just to know which line is the 131 in your controller?
You have an error here (don't know if it's the 131 line)
if (!$this->get('app.file')->upload($salon->getFiles(), 'salon'))
Here you send a collection to upload(), you said it yourself
One Salon to many Files
BUT before trying to hotfix this look at is tutorial here on how to handle multiple file upload.
Also this tutorial has the full demo source code available. The code is quite clear and you should be able to understand it easily.
Edit
If you don't want to rewrite your code you may want to hotfix your code like that
if (!is_null($edit_file)) {
$file_current = $salon->getFiles();
//$salon->getFiles($edit_file); What is the goal of this?
foreach ($salon->getFiles() as $file) {
// Note that now we send a single File object not a collection
if (!$this->get('app.file')->upload($file, 'salon')) {
$salon->setFiles($file_current); // You want to set the files no?
break;
}
}
}
This is 200% ugly, and I'm not even sure if it will work. You should really think about refactoring your code.
Edit 2
The problem you have now is that you are mixing your File object and the UploadedFile object from symfony.
You do $file_uploaded = $file->getPath(); then you have the error
Call to a member function getError() on string
and it's normal because getPath() return a string.
I assume you have look the Uploader Service of the symfony doc. You can see they pass an UploadedFile object which is part of the symfony package, not a custom entity.
If I wanted to do a quick fix, which is definitely not what I recommend, I'll do something like this
// Your controller (newAction)
foreach($myFiles['path'] as $new_file) {
// $new_file is an uploadedFile object, this is the file you want to upload
$file = new File();
$file->setPath($new_file);
$file->setSalon($salon);
$salon->addFile($file);
$uploadService->upload($file, $new_file, 'salon');
$em->persist($file);
}
// Your FileService
public function upload(File $file = null, UploadedFile $file_uploaded = null, $type) {
$path = $this->getDirectory($type);
if (is_null($file_uploaded) || is_null($file))
return false;
// Get file (Class UploadFile), No here you get the file path => a string
//$file_uploaded = $file->getPath();
if ($file_uploaded->getError())
return false;
//... end of your method
}
I have a FormType to be reused for editing & creating records. This form has one entity field which renders into a select populated depending the record id, so I need to skip this field when creating a new record. I read http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html and after changing some roots, everything seems to be fine until I'm trying to edit an existing record when I get stuck with this error:
ContextErrorException: Notice: Undefined variable: options in /Users/a77/Documents/DEV/UVox Com/src/Acme/DemoBundle/EventListener/VenueFieldSubscriber.php line 32
Mi VenuesFormType is :
namespace Acme\DemoBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Acme\DemoBundle\EventListener\VenueFieldSubscriber;
class VenuesType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', 'text')
->add('password', 'text')
->add('save', 'submit', array('label' => 'Save', 'attr' => array('data-loading-text' => 'loading', 'class' => "btn btn-primary")))
->addEventSubscriber(new VenueFieldSubscriber());
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Acme\DemoBundle\Entity\Venues'
));
}
/**
* #return string
*/
public function getName() {
return 'acme_demobundle_venues';
}
}
And my VenueFieldSubscriber is :
namespace Acme\DemoBundle\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\ORM\EntityRepository;
class VenueFieldSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
// Tells the dispatcher that you want to listen on the form.pre_set_data
// event and that the preSetData method should be called.
return array(FormEvents::PRE_SET_DATA => 'preSetData');
}
public function preSetData(FormEvent $event) {
$product = $event->getData();
$form = $event->getForm();
if (!$product || null === $product->getId()) {
// no action for new record
} else {
$form->add('user', 'entity', array(
'class' => 'AcmeDemoBundle:Users',
'property' => 'username',
'query_builder' => function(EntityRepository $er) use ($options) {
return $er->createQueryBuilder('u')
->Where('u.venue=?1')
->andWhere('u.usertype >1')
->orderBy('u.username', 'ASC')
->setParameter(1, $options['attr']['venueid']);
}
));
}
}
Any ideas, what I'm missing ? $options['attr']['venueid'] should give me the id of the record I'm editing... Thanks ;)
I assume that after
$product = $event->getData();
$product is an object of Acme\DemoBundle\Entity\Venues class.
Then instead of
->setParameter(1, $options['attr']['venueid'])
try
->setParameter(1, $product->getId())
I create a embedded form. How can I label in ItemType.php with the name from the db?
1.) Like:
$builder->add('id', 'checkbox', array('label'=> $v->getName(),...
2.) By the way symfony2 renders for each ItemType.php a Number 0,1,2. How can I get rid of it?
My action:
$task = new UserFriends();
foreach ($fb_friends as $k => $v) {
$name = $v->getName();
$friend_id = $v->getFriendId();
$id = $v->getId();
$t = new Item();
$t->name = $name;
$t->friendId = $friend_id;
$t->id = $id;
$task->getId()->add($t);
}
$form = $this->createForm(new CreateRequest(), $task, array());
Part of CreateRequest.php-form:
$builder->add('id', 'collection', array('type' => new ItemType(),
Part of my ItemType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('id', 'checkbox', array('label'=> 'Name', 'required' => false, 'mapped' => false));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Frontend\ChancesBundle\Entity\Item',
));
}
public function getName()
{
return 'item';
}
And Part of my Item.php-Entity
class Item
{
public $id;
public $friendId;
public $name;
public function getFriendId()
{
return $this->friendId;
}
You can pass an entity manager to your form and select whatever you want from the database.
In your controller (or whereever you are calling the form):
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(new MyFormType($blabla), $blabla, array('em' => $em));
In your form type:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$somethingFromDb = $options['em']->findByName('someName');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setRequired(array(
'em',
));
$resolver->setAllowedTypes(array(
'em' => 'Doctrine\Common\Persistence\ObjectManager',
));
}
Let me first explain what's I'm trying to do.
So I have a entity called property that have a field called type(it can be text, email, or multi_option) and another entity called propertyValue which is the value of the property
So I found this tutorial and my question is in the EventListener instead of a simple field how can I add a select or set of checkbox having the values of other entity?
Here you have my EventListener code and you can see where I' facing problem
<?php
namespace Comehoy\AdBundle\Form\EventListener;
use Symfony\Component\Form\Event\DataEvent;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvents;
class AddValueFieldSubscriber implements EventSubscriberInterface
{
private $factory;
public function __construct(FormFactoryInterface $factory)
{
$this->factory = $factory;
}
public static function getSubscribedEvents()
{
// Tells the dispatcher that we want to listen on the form.pre_set_data
// event and that the preSetData method should be called.
return array(FormEvents::PRE_SET_DATA => 'preSetData');
}
public function preSetData(DataEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
// During form creation setData() is called with null as an argument
// by the FormBuilder constructor. We're only concerned with when
// setData is called with an actual Entity object in it (whether new,
// or fetched with Doctrine). This if statement let's us skip right
// over the null condition.
if (null === $data) {
return;
}
// check if the ProprertyValue object is "new"
$type = $data->getI18nField()->getProperty()->getType();
if ('multi_option' === substr($type, 0, 12)) {
/*
*
* Here is the problem since I'm kind of sure this is not the way to do this
*
*/
$builder = $this->factory->createNamedBuilder('entity', 'value');
$builder->add('value', 'entity', array(
'class' => 'ComehoyAdBundle:Translation\AdPropertyOption',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('po')
->orderBy('po.value', 'ASC');
}
));
} else {
//It's not a multi option field so we use the type directly
$form->add($this->factory->createNamed($type, 'value'));
}
}
}
So what I'm basically try to do is to the same thing that I can do in buildForm of a type using $bulder parameter
Thanks
public function preSetData(DataEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
$form->add($this->factory->createNamed('type', 'name', $data->getValue(), array(
'class' => 'ComehoyAdBundle:Translation\AdPropertyOption',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('po')
->orderBy('po.value', 'ASC');
}
)));
}
If you are using SF 2.1 then:
public function preSetData(DataEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
$form->add($this->factory->createNamed('name', 'type', $data->getValue(), array(
'class' => 'ComehoyAdBundle:Translation\AdPropertyOption',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('po')
->orderBy('po.value', 'ASC');
}
)));
}