want to pre select my form in Symfony.
I do it with the Form builder. It works except of the child table is not saving.
My Invoice Type
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('invoiceNumber', 'hidden', array('label' => ''))
->add('date', 'date', array('label' => 'Field', 'data' => new \DateTime("now")))
->add('PaidPrice', 'money', array('label' => 'Bereits bezahlt', 'attr' => array('class' => '')))
->add('invoicepos', 'collection', array(
'type' => new InvoiceposType(),
'allow_add' => true,
'allow_delete' => true,
'cascade_validation' => true,
'by_reference' => true,
))
;
}
My invoicepos Type
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('pos', 'text', array('label' => '', 'attr' => array()))
->add('quantity', 'hidden')
->add('price', 'hidden')
->add('tax', 'hidden')
;
}
My Controller to start the Form
public function newAction($id) {
$em->persist($entInvoice);
//$em->flush($entInvoice); //works perfect, but i dont want to save that, just pre select for the form
$form = $this->createCreateForm($entInvoice);
return array(
'entity' => $entInvoice,
'form' => $form->createView(),
);
}
Code when i submit the form
public function createAction(Request $request) {
$entity = new Invoice();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('pspiess_letsplay_invoice_show', array('id' => $entity->getId())));
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
The data is there, but with nor relation!
What did i wrong?
Thanks for help.
Found a solution for my problem.
Before i flush i add the child entity...
foreach ($entity->getInvoicepos() as $entInvoice) {
$entity->addInvoicepos($entInvoice);
}
Related
I have this entity, using the query builder I get a list of options to display in a select, then I want to select one of this option. I'm using 'data' to select the option with id = 1 but it doesn't work, any idea on how to select an option?
thanks
public function buildForm(FormBuilderInterface $builder, array $options)
{
if($options['project'] instanceof Cpj\ProjectsBundle\Entity\Project){
$projectId = $options['project']->getId();
}
else{
$projectId = null;
}
if($options['sprint'] instanceof Cpj\ProjectsBundle\Entity\Sprint ){
$sprintId = $options['sprint']->getId();
}
else{
$sprintId = null;
}
$builder
->add('type', 'choice', array(
'choices' => array(
'' => '--',
'new' => 'New',
'bugfix' => 'Bugfix'
)))
->add('name', 'text')
->add('project', 'entity', array(
'class' => 'CpjProjectsBundle:Project',
'property' => 'name',
'empty_value' => '--',
'empty_data' => null,
'required' => false,
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->where("u.user = :id_user")
->setParameter('id_user', $this->user);
},
'data' => $projectId,
))
->add('sprint', 'entity', array(
'class' => 'CpjProjectsBundle:Sprint',
'property' => 'name',
'empty_value' => '--',
'empty_data' => null,
'required' => false,
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->where("u.user = :id_user")
->setParameter('id_user', $this->user);
},
'data' => $sprintId,
))
->add('importance', 'text')
->add('storypoints', 'text')
->add('description', 'textarea')
->add('howtoprove', 'textarea')
->add('save', 'submit');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'project' => null,
'sprint' => null,
));
}
public function __construct ($user)
{
$this->user = $user;
}
public function getName()
{
return 'story';
}
this is the action I'm using
public function newAction(Request $request)
{
$user = $this->getUser();
$story = new Story();
$id_project = $request->query->get('project');
$id_sprint = $request->query->get('sprint');
$form = $this->createForm(new StoryType($user), $story);
$form->getData()->getProject()->setValue($id_project);
$form->getData()->getSprint()->setValue($id_sprint);
$form->setData($form->getData());
$project = $this->getDoctrine()->getRepository('CpjProjectsBundle:Project')->findOneBy(array(
'id' => $id_project,
'user' => $user,
));
$sprint = $this->getDoctrine()->getRepository('CpjProjectsBundle:Sprint')->findOneBy(array(
'id' => $id_sprint,
'user' => $user,
));
$form = $this->createForm(new StoryType($user), $story, array(
'project' => $project,
'sprint' => $sprint,
));
$form->handleRequest($request);
if($form->isValid())
{
$story->setUser($user);
$em = $this->getDoctrine()->getManager();
$em->persist($story);
$em->flush();
return $this->redirect($this->generateUrl('cpj_stories_homepage'));
}
return $this->render('CpjProjectsBundle:Story:new.html.twig', array(
'form' => $form->createView(),
));
}
You may try just setting the project and the sprint on the new story entity before passing it to form create. Something like this:
public function newAction(Request $request)
{
$user = $this->getUser();
$story = new Story();
$id_project = $request->query->get('project');
$id_sprint = $request->query->get('sprint');
$project = $this->getDoctrine()->getRepository('CpjProjectsBundle:Project')->findOneBy(array(
'id' => $id_project,
'user' => $user,
));
$sprint = $this->getDoctrine()->getRepository('CpjProjectsBundle:Sprint')->findOneBy(array(
'id' => $id_sprint,
'user' => $user,
));
$story->setProject($project);
$story->setSprint($sprint);
$form = $this->createForm(new StoryType($user), $story);
$form->handleRequest($request);
if($form->isValid())
{
$story->setUser($user);
$em = $this->getDoctrine()->getManager();
$em->persist($story);
$em->flush();
return $this->redirect($this->generateUrl('cpj_stories_homepage'));
}
return $this->render('CpjProjectsBundle:Story:new.html.twig', array(
'form' => $form->createView(),
));
}
Then in your form would look like:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('type', 'choice', array(
'choices' => array(
'' => '--',
'new' => 'New',
'bugfix' => 'Bugfix'
)))
->add('name', 'text')
->add('project', 'entity', array(
'class' => 'CpjProjectsBundle:Project',
'property' => 'name',
'empty_value' => '--',
'empty_data' => null,
'required' => false,
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->where("u.user = :id_user")
->setParameter('id_user', $this->user);
},
))
->add('sprint', 'entity', array(
'class' => 'CpjProjectsBundle:Sprint',
'property' => 'name',
'empty_value' => '--',
'empty_data' => null,
'required' => false,
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->where("u.user = :id_user")
->setParameter('id_user', $this->user);
}
))
->add('importance', 'text')
->add('storypoints', 'text')
->add('description', 'textarea')
->add('howtoprove', 'textarea')
->add('save', 'submit');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'CpjProjectsBundle:Story'
));
}
You can also take out all of the stuff above $builder->add()... in the form
I have a Symfony 2 entity. When I create a new record, I must fill all the values using a form, but after saving it, one of the values, $amount shouldn't be updatable when I update the others members.
How can I accomplish this? It's possible to mark a form member as a read-only, in runtime?
By using the validation_groups and name options when creating your form, you can change the form.
The name attribute sets the form creation, and the validation_groups takes care of the validation.
For example, in the create/new method of your controller;
public function createAction(Request $request)
{
// Instantiate new Foo object
$client = new Foo();
// create the form (setting validation group)
$form = $this->formFactory->create('foo', $foo, array(
'name' => 'create',
'validation_groups' => array('create')
)
);
// form has been submitted...
if ('POST' === $request->getMethod()) {
// submits the form
$form->handleRequest($request);
// do validation
if ($form->isValid()) {
// do whatever
}
}
// either GET or validation failed, so show the form
return $this->template->renderResponse('FooBundle:foo:add.html.twig', array(
'form' => $form->createView(),
'foo' => $foo
));
}
And in the edit/update function of your controller;
public function updateAction($id, Request $request)
{
// Instantiate Client object
$client = new Foo($id);
// create the form (setting validation group)
$form = $this->formFactory->create('foo', $foo, array(
'name' => 'update',
'validation_groups' => array('update')
));
// form has been submitted...
if ('POST' === $request->getMethod()) {
// submits the form
$form->handleRequest($request);
// do validation
if ($form->isValid()) {
// do whatever
}
}
// either GET or validation failed, so show the form
return $this->template->renderResponse('FooBundle:foo/edit:index.html.twig', array(
'form' => $form->createView(),
'foo' => $foo
));
}
And your Form Type will look something like;
class FooType extends BaseAbstractType
{
protected $options = array(
'data_class' => 'FooBundle\Model\Foo',
'name' => 'foo',
);
private $roleManager;
public function __construct($mergeOptions = null)
{
parent::__construct($mergeOptions);
}
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->$options['name']($builder, $options);
}
private function create(FormBuilderInterface $builder, array $options)
{
// ID
$builder->add('Id', 'text', array(
'required' => true,
'label' => 'ID',
'attr' => array(
'placeholder' => 'Format: 2 alphanumeric (e.g. A1)'
)
));
// Name - only show on create
$builder->add('Name', 'text', array(
'required' => true,
'label' => 'Name',
'attr' => array(
'placeholder' => 'Your name'
)
));
// add the submit form button
$builder->add('save', 'submit', array(
'label' => 'Save'
));
}
private function update(FormBuilderInterface $builder, array $options)
{
// ID
$builder->add('Id', 'text', array(
'required' => true,
'label' => 'ID',
'attr' => array(
'placeholder' => 'Format: 2 alphanumeric (e.g. A1)',
)
));
// Name - just for show
$builder->add('Name', 'text', array(
'required' => true,
'label' => 'Name',
'attr' => array(
'readonly' => 'true' // stops it being editable
)
));
// add the submit form button
$builder->add('save', 'submit', array(
'label' => 'Save'
));
}
}
P.S. All my classes are declared as services, so how you call create forms/views/etc may be different.
I want to show the 'name' of my departments as a dropdown to my users and when they choose one, save its 'id' into the database. How can i do that? Below is my code. Currentlt its showing id and saving id.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('adress')
->add('city')
->add('area')
->add('departments', 'entity', array(
'empty_value' => '',
'class' => 'YdyaHospitalBundle:Department',
'query_builder' => function($repository) { return $repository->createQueryBuilder('t')->orderBy('t.id', 'ASC'); },
'property' => 'id',
'multiple' =>false,
'expanded' =>true,
))
;
}
Update
My controller action:
/**
* Creates a new Hospitals entity.
*
* #Route("/", name="hospitals_create")
* #Method("POST")
* #Template("YdyaHospitalBundle:Hospitals:new.html.twig")
*/
public function createAction(Request $request)
{
$entity = new Hospitals();
$form = $this->createForm(new HospitalsType(), $entity);
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('hospitals_show', array('id' => $entity->getId())));
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
/**
* Displays a form to create a new Hospitals entity.
*
* #Route("/new", name="hospitals_new")
* #Method("GET")
* #Template()
*/
public function newAction()
{
$entity = new Hospitals();
$form = $this->createForm(new HospitalsType(), $entity);
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
You can either implement a __toString() for your entity, or specify the property to display with:
->add('departments', 'entity', array(
'empty_value' => '',
'class' => 'YdyaHospitalBundle:Department',
'query_builder' => function($repository) { return $repository->createQueryBuilder('t')->orderBy('t.id', 'ASC'); },
// 'property' => 'id', --> Remove this
'multiple' => false,
'expanded' => true,
'property' => 'name' // Property used to display the entity
))
In your Controller you'll still be able to save your entity or the id of your entity to the db.
See documentation: http://symfony.com/doc/current/reference/forms/types/entity.html#property
I asked a question here How to use Repository custom functions in a FormType but nobody anwsered, so i did a little digging and advanced a little but i still get this error:
Notice: Object of class Proxies\__CG__\Kpr\CentarZdravljaBundle\Entity\Category
could not be converted to int in /home/kprhr/public_html/CZ_Symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php line 457
Now this is how my CategoryType looks like:
<?php
namespace Kpr\CentarZdravljaBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Bridge\Doctrine\RegistryInterface;
class CategoryType extends AbstractType
{
private $doctrine;
public function __construct(RegistryInterface $doctrine)
{
$this->doctrine = $doctrine;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Kpr\CentarZdravljaBundle\Entity\Category',
'catID' => null,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$someId = $builder->getData()->getId();
$param = ($someId) ? $someId : 0;
$catID = $options['catID'];
$builder->add('name', 'text', array('attr' => array('class' => 'span6')));
$builder->add('file', 'file', array('image_path' => 'webPath', 'required' => false));
$builder->add('parent', 'choice', array(
'choices' => $this->getAllChildren($catID),
'required' => false,
'attr' => array('data-placeholder' => '--Izaberite Opciju--'),
));
$builder->add('tags', 'tag_selector', array(
'required' => false,
));
$builder->add('status', 'choice', array(
'choices' => array('1' => 'Aktivna', '0' => 'Neaktivna'),
'required' => true,
));
$builder->add('queue', 'text', array('attr' => array('class' => 'span3')));
}
private function getAllChildren($catID)
{
$choices = array();
$children = $this->doctrine->getRepository('KprCentarZdravljaBundle:Category')->findByParenting($catID);
foreach ($children as $child) {
$choices[$child->getId()] = $child->getName();
}
return $choices;
}
public function getName()
{
return 'category';
}
}
I am accessing the CategoryRepository function findByParenting($parent) from the CategoryType and I am getting the array populated with accurate data back from the function getAllChildren($catID) but the error is there, i think that Symfony framework is expecting an entity field instead of choice field, but dont know how to fix it.
I also changet the formCreate call in the controller giving $this->getDoctrine() as an argument to CategoryType():
$form = $this->createForm(new CategoryType($this->getDoctrine()), $cat, array('catID' => $id));
Ok i managed to resolve the dilemma. The answer was easy all I had to do is change
$builder->add('parent', 'choice', array(
'choices' => $this->getAllChildren($catID),
'required' => false,
'attr' => array('data-placeholder' => '--Izaberite Opciju--'),
));
to this:
$builder->add('parent', 'entity', array(
'class' => 'KprCentarZdravljaBundle:Category',
'choices' => $this->getAllChildren($catID),
'property' => 'name',
'required' => false,
'attr' => array('data-placeholder' => '--Izaberite Opciju--'),
));
And change the getAllChildren(..) function so that it returns objects
private function getAllChildren($catID)
{
$choices = array();
$children = $this->doctrine->getRepository('KprCentarZdravljaBundle:Category')->findByParenting($catID);
foreach ($children as $child) {
$choices[$child->getId()] = $child->getName();
}
return $choices;
}
I changed it to:
private function getAllChildren($catID)
{
$children = $this->doctrine->getRepository('KprCentarZdravljaBundle:Category')->findByParenting($catID)
return $children;
}
Lots of thanks to user redbirdo for pointing out the choices option on an entity field.
It seems like you are doing something too much complicated.
You are on the right way when you write Symfony framework is expecting an entity field instead of choice field.
To do this, replace:
$builder->add('parent', 'choice', array(
'choices' => $this->getAllChildren($catID),
'required' => false,
'attr' => array('data-placeholder' => '--Izaberite Opciju--'),
));
by:
$builder->add('users', 'entity', array(
'class' => 'KprCentarZdravljaBundle:Category',
'property' => 'name',
'query_builder' => function(EntityRepository $er) use($catID) {
return $er->findByParenting($catID);
},
'required' => false,
'empty_value' => '--Izaberite Opciju--'
));
(and you don't need getAllChildren($catID) anymore unless used somewhere else)
http://symfony.com/doc/current/reference/forms/types/entity.html
I created form EditFormType with code:
// ...
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ...
$builder->addEventSubscriber(new UnsetReadOnlyForEmailField());
}
// ...
and UnsetReadOnlyForEmailField:
// ...
public static function getSubscribedEvents()
{
return array(
FormEvents::PRE_SET_DATA => 'preSetData'
);
}
public function preSetData(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
if ($data === null) {
return;
}
if ($data->getId() === null) {
$form->add(
'plainPassword',
'repeated',
array(
'type' => 'password',
'options' => array('translation_domain' => 'FOSUserBundle', 'required' => true),
'first_options' => array('label' => 'form.password'),
'second_options' => array('label' => 'form.password_confirmation'),
'invalid_message' => 'fos_user.password.mismatch',
)
);
}
}
// ...
Unfortunately required for repeated field doesn't work, field is't required. Any suggestions? If I do it wrong, then please write to set the fields in the form are required or not, depending on the form to edit or add. On add form required, on edit form not required.
I think you can do it in such way:
$form->add(
'plainPassword',
'repeated',
array(
'type' => 'password',
'options' => array('translation_domain' => 'FOSUserBundle'),
'first_options' => array(
'label' => 'form.password',
'required' => true
),
'second_options' => array(
'label' => 'form.password_confirmation',
'required' => true
),
'invalid_message' => 'fos_user.password.mismatch',
)
);