Related
I would like to display selection with options from DB. In this case, I am using EntityType with query_builder:
$builder
->add('internships', EntityType::class, array(
'class' => 'IndexBundle\Entity\Internship',
'property' => 'id',
'empty_value' => 'Choose',
'query_builder' => function (EntityRepository $er) use ($trainee) {
return $er->createQueryBuilder('i')
->where('i.trainee = :trainee')
->andWhere('i.state = :state')
->setParameter('trainee', $trainee)
->setParameter('state', 'unverified');
},
'constraints' => array(
new NotBlank(array(
'message' => 'choice.not.blank'
))
)
))
Now all is fine. I get select element with necessary options within with text of id value.
<select>
<option value="id">id</option>
...
</select>
How do I customize it?
For example I would like it to be combination of id and type table columns:
<select>
<option value="id">#id (type)</option>
...
</select>
You can use the choice_label option to customize your options.
You can either pass a function to retrieve the text you want, or you can add a getter to your entity if you reuse it at another place.
With a function:
$builder
->add('internships', EntityType::class, array(
'class' => 'IndexBundle\Entity\Internship',
'property' => 'id',
'empty_value' => 'Choose',
'query_builder' => function (EntityRepository $er) use ($trainee) {
return $er->createQueryBuilder('i')
->where('i.trainee = :trainee')
->andWhere('i.state = :state')
->setParameter('trainee', $trainee)
->setParameter('state', 'unverified');
},
'choice_label' => function ($internship) {
return '#'.$internship->getId().' ('.$internship->getType().')';
},
'constraints' => array(
new NotBlank(array(
'message' => 'choice.not.blank'
))
)
))
With a getter:
$builder
->add('internships', EntityType::class, array(
'class' => 'IndexBundle\Entity\Internship',
'property' => 'id',
'empty_value' => 'Choose',
'query_builder' => function (EntityRepository $er) use ($trainee) {
return $er->createQueryBuilder('i')
->where('i.trainee = :trainee')
->andWhere('i.state = :state')
->setParameter('trainee', $trainee)
->setParameter('state', 'unverified');
},
'choice_label' => 'idAndType',
'constraints' => array(
new NotBlank(array(
'message' => 'choice.not.blank'
))
)
))
Internship.php:
Class Internship
{
//...
public function getIdAndType()
{
return '#'.$this->id.' ('.$this->type.')';
}
}
Note:
For older Symfony versions (<= 2.6), this option was named property and use something supported by the PropertyAccessor component, so you can't use a function, only a getter for it.
I try to add a default option to an entity field in Symfony 2.3 form builder :
->add('destinataire','directory', array(
'required' => true,
'class'=> 'MLCUserBundle:Departement',
'multiple' => false,
'query_builder' => function (EntityRepository $er) use ($options) {
$data = $er->createQueryBuilder('d')
->where('d.id IN (:liste)')
->setParameter('liste',$options['listeId'])
->orderBy('d.name', 'ASC')
;
return $data;
},
'empty_data' => $all,
'choices' => $all,
)
)
without success I need some help! thx all !
i have tried various ways, but i cant get form to come back isValid() so i wanted to make sure i have this portion correct first.
<?php
namespace ABC\DeBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller,
Sensio\Bundle\FrameworkExtraBundle\Configuration\Route,
Sensio\Bundle\FrameworkExtraBundle\Configuration\Template,
Sensio\Bundle\FrameworkExtraBundle\Configuration\Method,
Symfony\Component\HttpFoundation\Request,
Symfony\Component\HttpKernel\Exception\HttpException,
Symfony\Component\Form\FormBuilderInterface,
Symfony\Component\Form\Forms,
Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension,
Symfony\Component\Form\Extension\Validator\ValidatorExtension,
Symfony\Component\Validator\Validation,
Symfony\Component\Validator\Constraints\Length,
Symfony\Component\Validator\Constraints\NotBlank,
Symfony\Component\Config\Definition\Exception\Exception,
Symfony\Component\HttpFoundation\Response,
ABC\CoreBundle\Controller\CoreController;
class DoSomethingController extends CoreController
{
protected $debug = FALSE;
public function doSomethingAction(Request $request)
{
/**
* build the form here
*
* Either use out custom build form object
* $form = $formFactory->createBuilder('form', $defaultData)
*
* Or alternatively, use the default formBuilder
* $form = $this->createFormBuilder($defaultData)
*/
$validator = Validation::createValidator();
$formFactory = Forms::createFormFactoryBuilder()
->addExtension(new HttpFoundationExtension())
->addExtension(new ValidatorExtension($validator))
->getFormFactory();
$defaultData = array(
'comment' => 'Type your comment here',
'name' => 'Type your name here',
'resources' => '{}',
'warning' => 'Warning, your still in debug mode on your controller.php'
);
//$form = $this->createFormBuilder($defaultData)
$form = $formFactory->createBuilder('form', $defaultData)
->setAction($this->generateUrl('do_something'))
->add("emails", 'text', array(
'label' => "Recipient's email address (separate with a comma)",
'constraints' => array(// constraints here
),
))
->add('comment', 'textarea', array(
'label' => "Leave a comment",
))
->add('name', 'text', array(
'label' => "Your name",
'constraints' => array(// constraints here
),
))
->add('email', 'email', array(
'label' => "Your email address",
'constraints' => array(// constraints here
),
))
->add('copy', 'checkbox', array(
'label' => "Send me a copy",
'required' => false,
))
->add('cancel', 'button', array(
'label' => "Cancel",
'attr' => array('class' => 'btn-branded'),
))
->add('save', 'submit', array(
'label' => "Email Resources",
'attr' => array('class' => 'btn-branded'),
));
//make resources visible by putting them into a text box
$resourceInputType = $this->debug ? 'text' : 'hidden';
$form->add('resources', $resourceInputType, array(
'constraints' => array(// constraints here
),
));
//add a visible warning input box, so we know were on debug, we don't want this released to live on debug.
$this->debug ? ($form = $form->add('warning', 'text')) : null;
$form .= $form->getForm();
//alternatively
//$form->bind($_POST[$form->getName()]);
//$form->handleRequest($request);
//validate
if ($form->isValid()) {
$data = $form->getData();
//run some data checks, then fire it off
$something = $this->DoSomething($data);
return $something;
//$return=array("responseCode"=>200, "data"=>$data);
// $return=json_encode($return); //json encode the array
// return new Response($return,200,array('Content-Type'=>'application/json'));//make sure it has the correct content type
}else
{
echo '<pre>';
var_dump('form is coming back as not isValid(), make sure debug is off, heres our errors list:<br>');
var_dump($form->getErrorsAsString());
echo '</pre>';
}
//its not a POST, or POST is invalid, so display the form
return $this->render($this->someTemplate, array(
'form' => $form->createView(),
));
}
}
1) Im a bit confused (oop wise) on the way to pass around this form object during conditional manipulation. Do i need to concatenate it when manipulating it or what does symfony offer to avoid this, or am i just passing the object around wrong? see this example to understand better this question. e.g. $form .= $form->getForm(); How would i properly concatenate this form object during manipulation, like i did when i used the ternary, to convine myself that when i pass this object around, its teh same object, and not a new one.
2) see any other problems that might be causing the breakage?
EDIT #Chausser
this is the latest code, streamlined a bit, that i am working with now using some apparently rare exmples found here http://api.symfony.com/2.5/Symfony/Component/Form/Forms.html. its still not coming back isValid() . Please compare my former, and new usage example of the form object.
<?php
/**
* #param Request $request
* #Route("/do/something", name="do_something", options={"expose"=true})
* #Method({"GET", "POST"})
* #return mixed
*/
public function doSomethingAction(Request $request)
{
$defaultData = array(
'comment' => 'Type your comment here',
'name' => 'Type your name here',
'resources' => '{}',
'warning' => 'Warning, your still in debug mode on your controller.php'
);
$resourceInputType = $this->debug ? 'text' : 'hidden';
$formFactory = Forms::createFormFactory();
$form = $formFactory
->createBuilder()
->setAction($this->generateUrl('do_something'))
->add("emails", 'text', array(
'label' => "Recipient's email address (separate with a comma)",
'constraints' => array(// constraints here
),
))
->add('comment', 'textarea', array(
'label' => "Leave a comment",
))
->add('name', 'text', array(
'label' => "Your name",
'constraints' => array(// constraints here
),
))
->add('email', 'email', array(
'label' => "Your email address",
'constraints' => array(// constraints here
),
))
->add('copy', 'checkbox', array(
'label' => "Send me a copy",
'required' => false,
))
->add('cancel', 'button', array(
'label' => "Cancel",
'attr' => array('class' => 'btn-branded'),
))
->add('save', 'submit', array(
'label' => "Email Resources",
'attr' => array('class' => 'btn-branded'),
))
->add('resources', $resourceInputType, array(
'constraints' => array(// constraints here
),
))
->getForm();
$form->handleRequest($request);
//validate
if ($form->isValid()) {
$data = $form->getData();
//run some data checks, then fire it off
$something = $this->DoSomething($data);
return $something;
//other options for returning
//$return=array("responseCode"=>200, "data"=>$data);
// $return=json_encode($something); //json encode the array
// return new Response($return,200,array('Content-Type'=>'application/json'));//make sure it has the correct content type
} else {
echo '<pre>';
var_dump('form is coming back as not isValid(), make sure debug is off, heres our errors list:<br>');
var_dump($form->getErrorsAsString());
echo '</pre>';
}
//its not a POST, or POST is invalid, so display the form
return $this->render($this->someTemplate, array(
'form' => $form->createView(),
));
}
EDIT
so now after my edits to get the form to not try and haldne the request, unless its teh POST request, not the GET request
if($request && $request->getMethod() == 'POST'){
$form->handleRequest($request);
//validate
if ($form->isValid()) {
$data = $form->getData();
//run some data checks, then fire it off
$something = $this->DoSomething($data);
return $something;
//other options for returning
//$return=array("responseCode"=>200, "data"=>$data);
// $return=json_encode($something); //json encode the array
// return new Response($return,200,array('Content-Type'=>'application/json'));//make sure it has the correct content type
} else {
echo '<pre>';
var_dump('form is coming back as not isValid(), make sure debug is off, heres our errors list:<br>');
var_dump($form->getErrorsAsString());
echo '</pre>';
}
}
which has led to the controller error mentioned below
Ok, it looks as if the validator extension, when used, was breaking, since the HttpFoundationExtension() wasnt being included. Apparently to use either the validator, or the factory builder (not sure which) it needs this extension as well.
working example, copied from initial example, with working parts added.
<?php
namespace ABC\DeBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller,
Sensio\Bundle\FrameworkExtraBundle\Configuration\Route,
Sensio\Bundle\FrameworkExtraBundle\Configuration\Template,
Sensio\Bundle\FrameworkExtraBundle\Configuration\Method,
Symfony\Component\HttpFoundation\Request,
Symfony\Component\HttpKernel\Exception\HttpException,
Symfony\Component\Form\FormBuilderInterface,
Symfony\Component\Form\Forms,
Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension,
Symfony\Component\Form\Extension\Validator\ValidatorExtension,
Symfony\Component\Validator\Validation,
Symfony\Component\Validator\Constraints\Length,
Symfony\Component\Validator\Constraints\NotBlank,
Symfony\Component\Config\Definition\Exception\Exception,
Symfony\Component\HttpFoundation\Response,
ABC\CoreBundle\Controller\CoreController;
class DoSomethingController extends CoreController
{
protected $debug = FALSE;
public function doSomethingAction(Request $request)
{
$validator = Validation::createValidator();
$builder = Forms::createFormFactoryBuilder()
->addExtension(new ValidatorExtension($validator))
->addExtension(new HttpFoundationExtension());
$defaultData = array(
'comment' => 'Type your comment here',
'name' => 'Type your name here',
'resources' => '{}',
'warning' => 'Warning, your still in debug mode on your controller.php'
);
$resourcesInputType = $this->debug ? 'text' : 'hidden';
$form = $builder->getFormFactory()
->createBuilder('form', $defaultData)
->setAction($this->generateUrl('do_something'))
->add("emails", 'text', array(
'label' => "Recipient's email address (separate with a comma)",
'constraints' => array(// constraints here
),
))
->add('comment', 'textarea', array(
'label' => "Leave a comment",
))
->add('name', 'text', array(
'label' => "Your name",
'constraints' => array(// constraints here
),
))
->add('email', 'email', array(
'label' => "Your email address",
'constraints' => array(// constraints here
),
))
->add('copy', 'checkbox', array(
'label' => "Send me a copy",
'required' => false,
))
->add('cancel', 'button', array(
'label' => "Cancel",
'attr' => array('class' => 'btn-branded'),
))
->add('save', 'submit', array(
'label' => "Email Resources",
'attr' => array('class' => 'btn-branded'),
))->add('resources', $resourcesInputType, array(
'constraints' => array( // constraints here
),
))
->getForm()
->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
//run some data checks, then fire it off
$something = $this->DoSomething($data);
return $something;
}
// initial render
return $this->render($this->someTemplate, array(
'form' => $form->createView(),
));
}
}
I'm trying to add two classes in a form. So I do for the second class:
foreach ($formOwnersDetails as $i => $details) {
$form = $form->add("member_{$i}_has_voting_denied", 'checkbox', array(
'data_class' => 'Pro\ConvocationBundle\Entity\OwnerDetails',
'property_path' => "votingDenied",
'label' => ' ',
'required' => false
));
but it gives me an error:
Neither property "votingDenied" nor method "getVotingDenied()" nor method "isVotingDenied()" exists in class "Pro\ConvocationBundle\Entity\Convocation"
Why is it looking for Pro\ConvocationBundle\Entity\Convocation when I'm adding data_class on the field definition?
I didn't check it but it should work:
Please check documentation for more information entity
$form = $form->add("member_{$i}_has_voting_denied", 'entity', array(
'class' => 'Pro\ConvocationBundle\Entity\OwnerDetails',
'property' => "votingDenied",
'label' => ' ',
'required' => false
));
I have a call at my controller:
Controller:
if($appointment->getAnamnese() == NULL){
$entity = new Anamnese($appointment);
$form = $this->createForm(new AnamneseType(),null,array('history' => 'Digite o Historico aqui'));
}else{
$entity = $appointment->getAnamnese();
$form = $this->createForm(new AnamneseType(), null, array('history' => $entity->getHistory()));
}
AnamneseType:
$builder->add('history', 'ckeditor', array(
'data' => $options['history'], 'toolbar' => $toolbar));
}
public function getDefaultOptions(array $options)
{
return array(
'history' => "Digite o Historico aqui"
);
}
and i want to inject that history information to my form but its not working as i thought it would be, just setting the 'data' option...
how can i do it?
the problem is that after inserting data, i cant put it back to the form..
Use the setData() function to set your data:
For example:
$form = $this->createForm(new AnamneseType())->setData($entity);
Or maybe even:
$form = $this->createForm(new AnamneseType(), $entity);
You're looking at it the wrong way.
You have to use options here.
to create the form:
$form = $this->createForm(new AnamneseType(), null, array('history' => $entity->getHistory()));
And your form should look like:
public function buildForm(FormBuilder $builder, array $options){
$toolbar = array(
array(
'name' => 'document',
'items' => array('Source','-','DocProps','Preview','Print','-','Templates')
),
array(
'name' => 'clipboard',
'items' => array('Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo')
),
array(
'name' => 'editing',
'items' => array('Find','Replace','-','SelectAll','-','SpellChecker', 'Scayt')
),
array(
'name' => 'basicstyles',
'items' => array('Bold','Italic','Underline','Strike','Subscript','Superscript','-','RemoveFormat')
),
'/',
array(
'name' => 'paragraph',
'items' => array('NumberedList','BulletedList','-','Outdent','Indent','-','Blockquote','CreateDiv','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock','-','BidiLtr','BidiRtl')
),
array(
'name' => 'links',
'items' => array('Link','Unlink','Anchor')
),
array(
'name' => 'insert',
'items' => array('Image','Table','HorizontalRule','Smiley','SpecialChar','PageBreak')
),
'/',
array(
'name' => 'styles',
'items' => array('Styles','Format','Font','FontSize')
),
array(
'name' => 'colors',
'items' => array('TextColor','BGColor')
),
array(
'name' => 'tools',
'items' => array('Maximize', 'ShowBlocks','-','About')
)
);
$builder->add('history', 'ckeditor', array( 'data' => $options['history'] , 'toolbar' => $toolbar));
}
...
public function getDefaultOptions(array $options)
{
return array(
'history' => "Digite o Historico aqui"
);
}
Well, looks like the form is generated in the second condition and $entity->getHistory() returns null.
Edit your controller code as below
$historyValue = 'Digite o Historico aqui'; // Default history value
if($appointment->getAnamnese()){
$entity = $appointment->getAnamnese();
// Checks whether the history is not empty (null or equals '' in this case)
if (!empty($entity->getHistory())) {
$historyValue = $entity->getHistory();
}
}
$form = $this->createForm(new AnamneseType(),null,array('history' => $historyValue));
I'd highly recommend you to read the official documentation.
Symfony Forms
Form data is supposed to be passed from a controller.
Replace
$form = $this->createForm(new AnamneseType($entity->getHistory()));
With
$form = $this->createForm(new AnamneseType(), array(
'history' => null === $entity->getHistory()
? 'Digite o Historico aqui'
: $entity->getHistory,
));
Remove constructor from the form class and replace
if($this->history != NULL){
$builder->add('history', 'ckeditor', array( 'data' => $this->history , 'toolbar' => $toolbar));
}else{
$builder->add('history', 'ckeditor', array( 'data' => "Digite o Historico aqui" , 'toolbar' => $toolbar));
}
With
$builder->add('history', 'ckeditor', array('toolbar' => $toolbar));
If you are going to map the data back to the entity check Forms official documentation
UPD:
To pass some value to a template from the history field edit its definition like:
$builder->add('history', 'ckeditor', array(
'attr' => array(
'toolbar' => $toolbar,
),
));
You can access the toolbar option by:
{{ form.history.get('attr').toolbar }}
There is better solution: Create Custom Form Type