-
-
Save webmozart/883293 to your computer and use it in GitHub Desktop.
<?php | |
protected function _editAction(Post $post) | |
{ | |
$em = $this->get('doctrine.orm.default_entity_manager'); | |
$factory = $this->get('form.factory'); | |
$form = $factory->create(new PostFormType()); | |
$form->setData($post); | |
if ($this->get('request')->getMethod() === 'POST') { | |
$form->bindRequest($this->get('request')); | |
if ($form->isValid()) { | |
$em->persist($post); | |
$em->flush(); | |
return new RedirectResponse($this->generateUrl('hello_index')); | |
} | |
} | |
return $this->render('MyHelloBundle:Hello:edit.html.twig', array( | |
'form' => $form->createView(), | |
)); | |
} |
<?php | |
namespace My\HelloBundle\Form; | |
use Symfony\Component\Form\FormBuilder; | |
use Symfony\Component\Form\Type\AbstractType; | |
use My\HelloBundle\Entity\Comment; | |
class PostFormType extends AbstractType | |
{ | |
public function buildForm(FormBuilder $builder, array $options) | |
{ | |
$builder | |
->add('title') | |
->add('file') | |
->add('content') | |
->add('abstract') | |
->add('enabled') | |
->add('publicationDateStart', 'date') | |
->add('commentsDefaultStatus', 'choice', array( | |
'choices' => Comment::getStatusCodes(), | |
)) | |
// the second parameter, $type, is null because we use auto-creation | |
->add('tags', null, array( | |
'expanded' => true, | |
'multiple' => true, | |
)) | |
->build('author', 'form', array('data_class' => 'My\HelloBundle\Entity\Author')) | |
->add('firstName') | |
->add('lastName') | |
->end(); | |
} | |
public function getDefaultOptions(array $options) | |
{ | |
return array( | |
'data_class' => 'My\HelloBundle\Entity\Post', | |
); | |
} | |
public function getName() | |
{ | |
return 'postform'; | |
} | |
} |
{% form_theme form _self %} | |
{{ form_enctype(form) }} | |
{{ form_widget(form) }} | |
{{ form_widget(form.firstName) }} | |
{% for child in form %} | |
{{ form_widget(child) }} | |
{% endfor %} | |
{{ form_widget(form.firstName, { 'attr': { 'class': 'foobar' } }) }} | |
{{ form_label(form.firstName, 'My label') }} |
How do you handle something kind like EntityChoiceList ? do I have to create my "choices" option array manually ?
@docteurklein Care to elaborate your question?
Sorry if misunderstood :)
I want my form to display a select
box corresponding to all the elements of a mongo database collection.
For that, I get an array of Documents and pass it to my choice
type via the choices
options.
the problem is that the dataTransformer attached to the choice
type is a ScalarToChoiceTransformer
and it can't handle Object transformation.
FormType:
$builder->add('frontend_template', 'choice', array(
'choices' => $this->getTemplateChoices() // this is an array containing Objects
))
I finally implemented my own DataTransformer and replaced the Scalar one.
Here is how I did:
$builder->get('frontend_template')->resetClientTransformers();
$builder->get('frontend_template')->appendClientTransformer(new DocumentToChoiceTransformer($this->dm, 'Test\Document\Template'));
Transformer:
<?php
namespace Test\BlockBundle\Form;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Component\Form\DataTransformerInterface;
use Test\Form\ToIdTransformable;
class DocumentToChoiceTransformer implements DataTransformerInterface
{
private $dm;
private $className;
public function __construct(DocumentManager $dm, $className)
{
$this->dm = $dm;
$this->className = $className;
}
public function transform($value)
{
if(null === $value) {
return '';
}
if(is_scalar($value)) {
return $this->dm->getRepository($this->className)->find($value);
}
if( ! $value instanceof ToIdTransformable) {
throw new \InvalidArgumentException(sprintf('Object must implement "ToIdTransformable" interface'));
}
return $value->getId();
}
public function reverseTransform($value)
{
if(is_scalar($value)) {
return $this->dm->getRepository($this->className)->find($value);
}
}
}
very helpful! thanks
I forgot to say that your domain objects must implement the ToIdTransformable
interface:
interface ToIdTransformable
{
function getId();
}
But I really would like to have the thoughts of @bschussek on this :)
@marijn: In such a case you would also have to manually prefill the relations of an object, if you use embedded forms.
You could avoid this mess by setting the empty data option:
But then we have the problem that we need to invoke this closure already when building the form in order to find out the type of the created object, which we can't, because we don't have a FormInterface object yet, only a FormBuilder.