Input validating forms Symfony - php

I've got an Integer field in Symfony form, which represents quantity - ofcourse it should be unable to pass the value equal or less than 0, so I've validated form in Entity and Form.
But - It's validated only when form is already sent. Is there any built-in method to validate form on input? I know that propably i would need to write own JS function to provide this, but I don't want to repeat someone others job :)

Found the solution.
To validate Symfony form on HTML side, you can just add an attribute to input field, reference: https://www.w3schools.com/htmL/html_form_attributes.asp
So, you form field should look like:
->add('quantity', IntegerType::class, ['label' => false,
'constraints' => new GreaterThan(array('value' => 0)),
'attr' => array(
'min' => '0',
)
])

Use pattern and min on your input. HTML should prevent form submit as long as the pattern isn't matched. (Careful, isn't doens't prevent submit if you're usin Javascript/Ajax to submit)
$builder->add('input_name', TextType::class, array(
'attr'=>array(
'pattern'=>'^[1-9][0-9]*' // 1 and above
'min'=>'1'
)
));
I'm using a TextType to remove the arrows in the input.
If you want to keep them, use NumberType.

A little addition, if you want to make sure a user can only enter a number you can add this bit of js to your code.
->add('quantity', NumberType::class, [ 'attr' =>
[
'oninput' => "this.value = this.value.replace(/[^0-9]/g, '').replace(/(\..*)\./g, '$1');"
] ])

Related

Validating Botdetect recaptcha in Symfony 4 Without using an entity

Is there any way to validate a BotDetect recaptcha in the symfony form builder?
I have the below form, which lets a user enter their email.:
$form = $this->createFormBuilder()
->add('email', EmailType::class,[
'label' => false,
'attr' => [
'style' => 'text-align:center;',
'value' => $email,
]
])
->add('captchaCode', CaptchaType::class, array(
'captchaConfig' => 'ExampleCaptcha'
))
->add('Do some shiz wif my email bruh.', SubmitType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
return $this->redirect('/unblock/'.$email);
}
The problem with this, is their documentation specifies a validation constraint in an Entity. My application does not have any entities (yet), but I would like to know if anyone has found a way to validate the captcha from the controller?
I'm fine with adding it to my entities when I create them , but I'm wondering how this would be done on an application that doesn't have any entities, or connection to a database.
I ended up using the beelabs google recaptcha bundle from packagist (If anyone is interested) at the link: https://packagist.org/packages/beelab/recaptcha2-bundle
Their documentation tells you pretty much everything you need to know about installation and setup.
The one drawback is that it still lets the form submit even though you havent clicked the I am not a robot checkbox, so you would need to validate whether it's been clicked on the PHP end.
You can use this to get the response, which is usually either a hash, or an empty field.
$recaptcha = $request->get('g-recaptcha-response', '');
use Captcha\Bundle\CaptchaBundle\Validator\Constraints\ValidCaptcha;
$form = $this->createFormBuilder()
->add('captchaCode', CaptchaType::class, [
'captchaConfig' => 'LoginCaptcha',
'constraints' => [
new ValidCaptcha([
'message' => 'CAPTCHA validation failed, try again.'
])
]
]);

Getting empty_data to work in a Symfony 2 application

I am adding fields to a project based on a project based on Symfony 2 and Sonata. I am trying to follow the instructions from this answer. In one of my admin classes, I have inserted the following code:
$default = 'Germany';
if (!$this->getUser()->hasRole(User::CONTENT_SUPPLIER)) {
$formMapper
->tab('Distribution')
->with('Distribution')
->add(
'module',
null,
[
'empty_data' => $default,
]
)
->add(
'distributions',
'distribution_list',
[
'label' => false,
'required' => 'false',
'disabled' => true
]
)
->add('plannedDistributions')
->end()
->end()
;
}
... and while I expect to see a reference to the "Germany" object by default in my form, I instead see an empty field. Should I be passing in an object rather than a string? Is what I'm trying to do even possible? What am I doing incorrectly here?
I think you missed a crucial bit in the documentation regarding empty_data:
This option determines what value the field will return when the submitted value is empty (or missing). It does not set an initial value if none is provided when the form is rendered in a view.
This means it helps you handling form submission with blank fields.
That means empty_data will populate your model with the data when the form was submitted without a default value.
I'm not familiar with the $formMapper used in your snippet, but in a typical Symfony-Controller you could create your form like this:
$form = $this->createForm(MyForm::class, $initialData);
In this case $initialData contains a property Distribution with the value Germany. Alternatively you could try providing the value in your frontend.
To set default data use option 'data'.
Sample:
//Use block
use Symfony\Component\Form\Extension\Core\Type\TextType;
//...
$formMapper
->add('module', TextType::class,[
'data' => 'Gearmany',
]);

How to use unmapped field in Symfony form to adjust data post submit?

I have two fields in my entity contractLength and contractEndDate. The aim is to be able to specify EITHER a contractLength OR a contractEndDate.
To accomplish this I have added an unmapped field to the form useBespokeEndDate, of checkbox type.
I want to be able in the form class ContractType to listen for the submit event and then check if the checkbox is ticked, if it is then proceed as normal but if it is not ticked (so we are using contractLength) then set the contractEndDate field to null.
I believe I should be using Event Listeners as detailed here http://symfony.com/doc/master/form/dynamic_form_modification.html#customizing-your-form-based-on-the-underlying-data (under the Dynamic Generation for Submitted Forms heading) to listen for the POST_SUBMIT event and then check the value of useBespokeEndDate and then modify the data as appropriate. However, I'm confused as to how exactly to get the form data for the unmapped field and then to also modify the actual data of the form.
My buildForm method in ContractType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('useBespokeEndDate', CheckboxType::class, array(
'label' => 'Use Bespoke Contract End Date?',
'empty_data' => false,
'mapped' => false
))
->add('contractLength', ChoiceType::class, array(
'choices' => array(12 => 12, 24 => 24, 36 => 36, 48 => 48, 60 => 60),
'label' => 'Contract Length (months)'
))
->add('contractEndDate', DateType::class, array('label' => 'Contract End Date'))
->add('save', SubmitType::class, array('label' => 'Save'));
$builder->addEventListener(FormEvents::POST_SUBMIT,
// Do something here to modify the data
);
}
Had the same problem, and I could access the unmapped values this way :
// in your POST_SUBMIT callback :
$form = $event->getForm();
$contract = $event->getData();
// get the unmapped value :
$useBespokeEndDate = $form->get('useBespokeEndDate')->getData();
// .. continue
I've got a similar situation where I have an option field, it's use (and therefore value) depending on a radio button group.
Rather than making a dynamic form, I instead separated the form from the entity, and actually ended up created a sub-form (Type) that had its own data_class Form configuration option and Data Mappers to convert the value objects to the entities.
There are useful blog posts with more information about Value Objects in forms and Creating a Custom Data Mapper for Symfony Forms.
For me, this alos gives the advantage of moving some quite complex checks into their own smaller class, and making the code more reusable.

Symfony 2.3: Remember form inputs while visiting another site

What I have:
A form with several different input fields etc. The interesting part is a collection field:
$builder->add( 'publicationAuthors', 'collection', array (
'type' => new AuthorPublicationType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'label' => 'Autoren'
));
This collection refers to another FormType, including only an entity field and an order id:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add( 'author', 'entity', array (
'class' => 'indPubBundle:Author',
'multiple' => false,
'label' => 'Autor',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder( 'a' )
->orderBy( 'a.author_surname', 'ASC' );
}
$builder->add( 'order_id', 'hidden');
));
}
Via JS I am able to add new collection form fields to my form so the user can then choose several of the authors and order them.
What I need:
So far, the user can only choose existing authors due to the entity field. I want to enhance the form such that the user is also able to create new authors and use these in the form. I thought of adding a button which redirects the user to a new form where he can create a new author. Then, after submitting that form, the user should be redirected back to the original form and continue to fill it out.
The main problem here is, that I want to remember the user's previous inputs to the original form so that he doesn't need to start all over. Is there a way to remember these inputs while the user is using the author creation form?
I thought of remembering the data in the session, but there is a problem with that: If the user would open a new tab, he might overwrite the old form inputs, since the session ID is the same for both tabs.
Okay I found a solution that is satisfying for me.
Basically, I take the whole form data, serialize it and remember that in a hidden form field.
Because the serialize function returns several signs that are not useable in html, I also encode the string with base64.

Symfony2 Form validation dependency between form_types in one form

In my symfony2 project I created a new FormType which is called "ChoiceAndOrTextType" which is a list of choices (checkboxes) but the user can also check the "others" option and write his answer into a textfield.
The code is like this one here in the answer of bschussek:
Use a conditional statement when creating a form
$builder
->add('choice', 'choice', array(
'choices' => $options['choices'] + array('Other' => 'Other'),
'required' => false,
))
->add('text', 'text', array(
'required' => false,
))
->addModelTransformer(new ValueToChoiceOrTextTransformer($options['choices']))
;
Now i want to validate this correctly, so when the user checks "Others" then the textfield needs to be filled out, if "Others" isn't checked it can be blank. (Kind of dependent validation).
How do I do this?
You need to use two validation constraints, for example in validation.yml yaml file

Categories