Symfony 4 - Default value form not working - forms

I have a little problem I don't understand.
I want to display my errors in the same location at the top of the form, I used form_errors(form)
Then in my form, I added a default value to my fields.
        
$resolver->setDefaults([
'data_class' => Whitelist::class,
'error_bubbling' => true
]);
Currently, it does not work and my errors appear in their respective fields.
But if I put this option 'error_bubbling' => true to my field, it works. Why by default it does not work?
->add('firstName', null, [
'label' => "Prénom de votre personnage",
'error_bubbling' => true
])
Sorry for my english, thanks.

'error_bubbling' => true means that the error will "bubble" up to the form, where you are trying to display it.
From the docs:
error_bubbling
type: boolean default: false unless the form is compound
If true, any errors for this field will be passed to the parent field or form. For example, if set to true on a normal field, any errors for that field will be attached to the main form, not to the specific field.

Related

How to add an error to a constraint in form?

Using Symfony 3.2 on Ubuntu 16.04
I created a FormType.php with several fields. One of them is a phone number, so I added a constraint where only numbers could be accepted. Here is the code for the phone form
->add('authorPhone', NumberType::class, array('label' => 'Numéro de téléphone',
'required' => true,
'attr' => array(
'class' => 'validate',
'id' => 'icon_telephone'
),
'constraints' => array(new Regex("#^0[1-9]([-. ]?[0-9]{2}){4}$#"))
))
After that, in my controller I added an error to tell that numbers only need to be filled in
public function indexAction()
{
$form = $this->createForm(FormType::class);
$form->get('authorPhone')->addError(new FormError('error message'));
return $this->render('app/main/index.html.twig', array(
'form' => $form->createView()
));
}
But when I look at my page the error message is actually showing without having filled the field. And of course I don't want that.
(you can see under "Numéro de téléphone", which means phone number)
I only want numbers in my phone number field, and if there are letters, an error should be displayed or something saying it's not right.
Standard how to to this stuff in Symfony is to define an entity with contraints and error messages and then create entity bound form which will handle validation based on entity's contraints automatically.
But if you need, for some reason, independent form, it can be done to. The addError() method is for adding error "state" the the form field (e.g. for own validation) and you're adding the error by default right after the form is created. That's the reason why the error shows constantly.
UPDATED:
The right way to assign an error message to a form field is by the invalid_message property (which is showed when the entered value doesn't correspond with the field type). But when there's a constraint used for validation, then the err message has to be set according to the constraint validator - so, in your case, by associative array with pattern and message keys.
Next thing need to be corrected is TextType instead of NumberType, because when the NumberType is used, then it won't allow to enter dashes and also automatically trims leading zeros in numbers - so bad for phone numbers :-)
->add('authorPhone', TextType::class, array(
'label' => 'Numéro de téléphone',
'required' => true,
'attr' => array(
'class' => 'validate',
'id' => 'icon_telephone'
),
'constraints' => array(new Regex(
array(
'pattern' => '#^0[1-9]([-. ]?[0-9]{2}){4}$#',
'message' => 'Phone error message'
)
)),
))
And last thing to review - in the controller (after form declaration) has to be form submission handling routine:
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
....
You can learn more in Symfony's form submission handling: http://symfony.com/doc/current/forms.html#handling-form-submissions
Form rendering is fairly simple. Twig syntax to render whole form:
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
or, if you want to selectively render fields one by one:
{{ form_start(form) }}
{{ form_row(form.authorPhone) }}
{{ form_row(form.submit) }}
{{ form_end(form) }}
It'll renders complete field including labels and errors

Sylius custom fields are not validated in form

I am overriding the register page (overriding the Customer object) ; I have added "Type", which is a ChoiceType expanded (3 radio buttons), and I have added the defaultAddress fields (in which I have added 3 fields).
When I display the form, all these fields have a red star to show there are required, but when I submit the form, if I don't put anything in these fields, the form is submitted anyway and I have a database error because these fields are empty.
Here is my code :
CustomerRegistrationTypeExtension.php :
$builder->add('type', ChoiceType::class, [
'choices' => array('Particulier' => Customer::TYPE_PARTICULIER, 'Professionnel' => Customer::TYPE_PRO, 'Projet à but non lucratif' => Customer::TYPE_PROJET),
'expanded' => true,
'label' => 'Vous êtes',
'choice_attr' => array('onclick' => 'alert(\"click\")')
])
->add('siren', TextType::class)
->add('denomination', TextType::class)
->add('defaultAddress', AddressType::class);
AddressTypeExtension.php
$builder->add('showOnMap', CheckboxType::class)
->add('geocodeLat', HiddenType::class)
->add('geocodeLng', HiddenType::class);
_address.html.twig :
{{ form_row(form.showOnMap, {'label' : 'address.showMap.label'}) }}
{{ form_row(form.geocodeLat)}}
{{ form_row(form.geocodeLng)}}
_form.html.twig
{{ form_row(form.type) }}
Any idea ?
Thanks !
Red asterisk near the field is just an UI feature. To require some fields, you must specify theirs validation configuration. Check out Symfony validation documentation to get required info, all of it should perfectly work in Sylius ;)
One important thing - remember to set sylius in groups parameter when defining constraints, it is a default validation group in Sylius.

Symfony2 choice field : empty value

I'm stumbling upon a really simple question and I can't find out what I'm doing wrong :
I have an entity Post which can have a type, in my class declaration :
/**
* #ORM\Column(name="type", type="text", nullable=true)
*/
private $type;
Then I want a form to create Posts :
In my PostType::buildForm() function :
$builder->add('type', 'choice', array(
'empty_data' => null,
'empty_value' => 'No type',
'multiple' => false,
'expanded' => true,
'choices' => \MyBundle\Entity\Application\Post::getTypes(), /* returns array('TYPE1' => 'TYPE_1', 'TYPE2' => 'TYPE_2', ...) */
'required' => true,))
The plan is to have a radio list with :
Type 1
Type 2
Type 3
No type
But it seems like if I choose the option 'No type', the form won't validate, without giving any explicit error. Same thing happens with 'required' => false, with 'placeholder' instead of 'empty_value', ...
Can you spot my mistake ?
What am I doing wrong ?
Thanks :)
My mistake didn't come from the Type or the Entity, it came from the twig widgets overloading.
I was not displaying the value="" if {{ value }} was empty.
Make sure value="" is inside your "None" input radio tag, and in your other input radio tags aswell, of course !
Hope it helps someone ;)
You can't have an empty value on a choice field type and have it required.
You are saying it must exist but may be empty, a contradiction.
It will work if you drop the 'required' => true

Input password blank override user password

im developing an user profile section for my app. I have a password field to allow the user change your password.
I have a problem with this. When the user fill the password input, your password are updated correctlly. But when, the user not fill the input, the user password set a blank value.
I like if that user not fill the input, keep the current password.
It is my form definition:
$builder
->add('email','text',array(
'required' => false
))
->add('clave','password', array(
'required' => false,
'always_empty' => true
))
->add('reClave','password',array(
'mapped' => false,
'required' => false
))
->add('telefonos','collection', array(
'type' => new TelefonoType(),
'required' => false,
'allow_add' => true,
'allow_delete' => true
))
->add('submit', 'submit')
->add('reset', 'reset')
;
Note: I dont use FOSUserBundle.
Any ideas ?
Like #Tejas suggested you, you can check in your User::setPassword() function if your param is empty and set it only if it's not. But it's not the best way because you override a form constraint in your entity (the NotBlank constraint on a password).
A better and simple solution would be to display two separated forms on your profile edition page. First for common data, and second for password update. Then you can a NotBlank constraint on your field, make it repeated type (doc here) if it's not, also add more constraints like "more than 6 characters" (Range) or "at least letters and numbers" (Regex).
The last solution is to use Form Events to control your validation rules according to your form : creation or edition. But it is more complecated to manipulate.

symfony2 form collection with an empty row

I have a form with an collection:
$builder->add('languages', 'collection', array(
'type' => new LanguageType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
));
In the twig-template I render an additional row with an empty (LanguageType). For that I use the prototype and replace the name.
In the Controller I bind the Request and discard the "empty" Language in the setter:
public function addLanguage($lang)
{
if($lang->getLanguage())
{
$this->languages->add($lang);
}
// discard the others
}
For some Reason the "empty" row throws an validation error via the NotBlank validator.
My only working solution is to remove the empty row from the raw-Request but thats ugly.
Your solution is valid.
Otherwise you could set the option required to false on $builder->add('lang') but then you would have to do some extra checking yourself.
$builder->add('lang', 'text', array(
'required' => false
));
Documentation about the required option.
Or you can create some JS code that injects the name of the input only when the field is not empty (input with an empty name doesn't have its value sent through). It isn't great either but it works.