In my TopicType class, I used :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', 'text')
->add('content', 'ckeditor', array(
'label' => 'Contenu',
'config_name' => 'my_custom_config',
'config' => array('language' => 'fr'),))
->add('save', 'submit')
;
}
How can I get autofocus on my first field "title", when i display the form?
$builder->add('title', 'text', array(
'attr' => array(
'autofocus' => true
)
);
The realy crossbrowser way is to type
$builder->add('title', 'text', array(
'attr' => array(
'autofocus' => null
)
);
This code produces just autofocus attribute without = sign and any value.
Related
In my Symfony4 project, I have an entity called 'Customer'. This entity has an extra validation method to do some extra validation for the field 'zip code'. When a zip code is invalid i receive a general error.
/**
#Assert\IsTrue(message = "invalid.zipcode")
*/
public function isZipCodeValid()
{
...
return false;
}
I would like to map this specific error to the 'zip code' field so i can show users which field is causing the issue.
I have tried the following code in the CustomerForm, as mentioned in the Symfony documentation: https://symfony.com/doc/current/reference/forms/types/form.html#error-mapping
....
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Customer::class,
'error_mapping' => [
'isZipCodeValid' => 'zip_code',
],
]);
}
Unfortunately this keeps sending a global error after posting my form. Not sure why.. Does anyone knows how to fix this? Thanks!
buildForm:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, array('label' => 'Name', 'attr' => array('size' => '50')))
->add('address_line', TextType::class, array('label' => 'Addressline', 'attr' => array('size' => '50')))
->add('zip_code', TextType::class, array('label' => 'Zipcode', 'attr' => array('size' => '20')))
->add('city', TextType::class, array('label' => 'City', 'attr' => array('size' => '50')));
}
I have this form and I want to checked if one of the two fields (numberPlate or expirationDate) is filled.
This is my buildForm:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('type', ChoiceType::class, array(
'choices_as_values' => true,
'required' => true,
'label' => 'Tipo Veicolo',
'empty_data' => '',
'empty_value' => '',
'attr' => array('class'=> 'form-control select2'),
'choices' => array('Auto' => 'Auto', 'Moto' => 'Moto', 'Camper' => 'Camper' ,'Barca' => 'Barca')
))
->add('numberPlate', TextType::class, array(
'label' => 'Targa',
'required' => false,
'attr' => array(
'class'=> 'form-control',
'minlength' => 5,
'maxlength' => 7
)
))
->add('expirationDate', DateTimeType::class, array(
'label' => 'Scadenza',
'widget' => 'single_text',
'input' => 'datetime',
'format' => 'dd/MM/yyyy',
'attr' => array('class'=> 'form-control')
))
;
}
You can ensure one of the fields are not empty, by adding a callback constraint to your entity.
namespace App\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
class YourModel
{
/**
* #Assert\Callback
*/
public function validate(ExecutionContextInterface $context)
{
if (!$this->numberPlate && !$this->expirationDate) {
$context->buildViolation('Targa or Scadenza is required')
//optionally display the error at the numberPlate field, omit to display at the top of the form errors
->atPath('numberPlate')
->addViolation()
;
}
}
}
Then update your Scadenza field as not required.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
//...
->add('expirationDate', DateTimeType::class, array(
'label' => 'Scadenza',
'required' => false,
'widget' => 'single_text',
'input' => 'datetime',
'format' => 'dd/MM/yyyy',
'attr' => array('class'=> 'form-control')
))
;
}
When the form is submitted it will execute the YourModel::validate method, and if the numberPlate and expirationDate are empty, it will fail $form->isValid().
Be sure to clear your cache after making the changes, to refresh the annotations.
NOTE: This will apply to any/all forms this entity model is used in,
to separate the validation you will need to implement validation groups
I'm having a hard time building forms for my entities that are themselves built with traits.
For example my "Article" entity only contains the link to the category and 2 pics, the rest of its properties is in the SeoTrait (title, meta_title, meta_desc, content, etc...), ValidTrait (isValid true/false)... which I want to use for other entities.
It all works fine for doctrine, that generates my schema with all the fields from the Traits in each entity that use them. The problem is for the forms :
I've created the SeoTraitType for the "SEO" properties :
class SeoTraitType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, array(
'label' => 'Nom'
))
->add('metaTitle', TextType::class, array(
'label' => 'Meta Title'
))
->add('metaDescription', TextareaType::class, array(
'label' => 'Meta Description'
))
->add('metaKeywords', TextType::class, array(
'label' => 'Keywords'
))
->add('content', TextareaType::class, array(
'label' => 'Content'
))
;
}
}
And then I'm using it in my ArticleType :
class ArticleType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('seo', SeoTraitType::class, array(
'label' => 'Seo',
'mapped' => false
))
->add('isValid', ValidTraitType::class, array(
'label' => 'Valid',
'mapped' => false
))
->add('save', SubmitType::class, array(
'label' => 'form_save',
'translation_domain' => 'back_default'
));
;
}
}
The two problems I have here is that I must set mapped => false for the 2 TraitTypes when I want to embed them in my main entity's form
And then in my form I get article[seo][name] for the SeoTrait's fields, so I can't really use the $form->handleRequest() methods and all... to handle the submission of my form
I was wondering if there is a special way to do this within the provided methods of the form component, or if I just have to handle the request myself and parse the trait arrays myself to build my entity before saving it ? I couldn't really find anything on the internet :(
One way to solve your problem is to transform your class SeoTraitType into a Trait.
like:
trait SeoTraitType
{
public function buildSEOForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, array(
'label' => 'Nom'
))
->add('metaTitle', TextType::class, array(
'label' => 'Meta Title'
))
->add('metaDescription', TextareaType::class, array(
'label' => 'Meta Description'
))
->add('metaKeywords', TextType::class, array(
'label' => 'Keywords'
))
->add('content', TextareaType::class, array(
'label' => 'Content'
))
;
}
}
Then:
class ArticleType extends AbstractType
{
use SeoTraitType;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->buildSEOForm($builder, $options);
$builder
->add('isValid', ValidTraitType::class, array(
'label' => 'Valid',
'mapped' => false
))
->add('save', SubmitType::class, array(
'label' => 'form_save',
'translation_domain' => 'back_default'
));
;
}
}
You can also do this with static method. Not a big fan of Trait.
Ok so the Trait solution works fine, but I chose to go for this method here :
https://symfony.com/doc/current/form/inherit_data_option.html
Thanks so much guys, I was pretty sure that the solution would be somewhere in the documentation but couldn't find it !
You can see here my FormType.
And I would like to let appear a drop down menu with the pupils name as a value and the id as the key.
Something like this :
->add('eleve', 'choice', array(
'choices' => array(id of the pupil => name of the pupil),
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('eleve', 'entity', array(
'class' => 'WCSCantineBundle:Eleve'
))
->add('status', 'choice', array(
'choices' => array('0' => 'Non-Inscrit'),
'label' => false
))
->add('date', 'text', array(
'label' => false
))
->add('Ajouter', 'submit');
}
Thank you for your help.
->add('eleve', 'entity', array(
'class' => 'WCSCantineBundle:Eleve'
'choice_label' => 'pupilname',
))
here pupil name would be the name of the field in your Eleve entity
this would create a drop down menu with all the Eleve records loaded from the database, on submission the id of the selection would be submitted through the form
Read more here
I have an unsubscribe form, where the first field is a entity field, fetching my UnsubscribeType entities :
$builder
->add('type', 'entity', array(
'class' => 'Evo\SubscriptionBundle\Entity\UnsubscribeType',
'property' => 'name',
'label' => 'Choose process type',
'empty_value' => 'Choose an option',
'empty_data' => null,
'label_attr' => array(
'class' => 'control-label',
),
'attr' => array(
'class' => 'form-control',
),
))
this collection contains 2 entities, #1 and #2. I would like to remove entity #2 from the select field if a custom test about the authed user fails.
Let's say I'd to test $this->getUser()->getCustomField(). If it is false, then i would like to remove entity #2 from the select field containing my UnsubscribeType entities.
Any idea how to do that ?
Perhaps you could pass to the form builder the result of the test from you controller and then, either use 'property' => 'name' or 'choices => // fetch entity #1 here.
So, something like this
public function buildForm(FormBuilderInterface $builder, array $options)
{
if($options['customField'] === TRUE)
{
$builder
->add('type', 'entity', array(
'class' => 'Evo\SubscriptionBundle\Entity\UnsubscribeType',
'property' => 'name',
// ..
;
}
else
{
$builder
->add('type', 'entity', array(
'class' => 'Evo\SubscriptionBundle\Entity\UnsubscribeType',
'choices' => $options['customField'],
// ..
;
}
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
// ..
$resolver->setRequired(array(
'customField'
));
}
And in your controller:
$form = $this->get('form.factory')->create(new EntryType(), $entry, array(
'customField' => $this->getUser()->getCustomField()
));
with getCustomField() returning either true or the entity (or collection of entities) that you want populating your select field. My solution would involve changing the getCustomField method though, don't know if that would suit.