A real time backend validation for Symfony2
// composer.json
{
"require": {
// ...
"nebumix/rt-validation-bundle": "dev-master"
}
}
// app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new Bmatzner\JQueryBundle\BmatznerJQueryBundle(),
new FOS\JsRoutingBundle\FOSJsRoutingBundle(),
new Nebumix\rtValidationBundle\NebumixrtValidationBundle(),
// ...
);
}
$ php composer.phar update nebumix/rt-validation-bundle
# app/config/routing.yml
fos_js_routing:
resource: "@FOSJsRoutingBundle/Resources/config/routing/routing.xml"
Nebumix_rtV_routing:
resource: "@NebumixrtValidationBundle/Resources/config/routing.yml"
Given your server's public directory is named "web", install the public vendor resources
$ php app/console assets:install web
Optionally, use the --symlink attribute to create links rather than copies of the resources
$ php app/console assets:install --symlink web
# app/config/securityRT.yml
parameters:
nebumix_rtvalidation.check.class: Nebumix\rtValidationBundle\Controller\CheckController
# app/config/config.yml
imports:
// ...
- { resource: securityRT.yml }
Installing NeburtValidation, you installed automatically also bmatzner/jquery-bundle
and friendsofsymfony/jsrouting-bundle
We need to configure friendsofsymfony/jsrouting-bundle, you can look the official documentation in the official page.
I suggest to add these lines in app/config/config.yml
:
# app/config/config.yml
fos_js_routing:
routes_to_expose: [ nebumixrt_validation_check ]
The route name you need is nebumixrt_validation_check
Add this line in your layout:
<script type="text/javascript" src="{{ asset('bundles/bmatznerjquery/js/jquery.min.js') }}"></script>
Add these two lines in your layout:
<script src="{{ asset('bundles/fosjsrouting/js/router.js') }}"></script>
<script src="{{ path('fos_js_routing_js', {"callback": "fos.Router.setData"}) }}"></script>
Add this line in your layout:
<script type="text/javascript" src="{{ asset('bundles/nebumixrtvalidation/js/nebumix_r_t_validation.js') }}"></script>
This example supposed to have in the page a form with fields called nameField
, nameField1
... It will be explain better in the example.
To validate in real time a form field, you need to call a function to check your field. I use the .focusout function.
To validate a text field you need to add in your layout:
$(function() {
$('#nameForm_nameField').focusout(function() {
check_field('nameValidation', 'nameForm_nameField');
});
$('#nameForm_nameField1').focusout(function() {
check_field('nameValidation', 'nameForm_nameField1');
});
//...
$('#nameForm_nameFieldN').focusout(function() {
check_field('nameValidation', 'nameForm_nameFieldN');
});
//if you have a radio or checkbox
$('#nameForm_nameFieldN').onchange(function() {
check_field_check('nameValidation', 'nameFieldToCheck');
});
});
You need to replace nameField
with the field name you want to validate and nameForm
with the form name (generally the id field is made using nameForm_nameField).
You need to replace nameValidation
with a name, it must to be different for each form.
Is not necessary nameValidation
is the real form name, it needs just to distinguish the form fields in the validation file.
parameters:
nebumix_rtvalidation.check.class: Nebumix\rtValidationBundle\Controller\CheckController
nameValidation:
nameForm_nameField:
NotBlank:
message: Field is required.
Regex:
pattern: "/^\d+$/"
message: insert an integer
nameForm_nameField1:
NotBlank:
Length:
min: 3
nameFieldToCheck:
NotBlank:
You have to use the name you used as nameValidation
in the javascript function followed by the name used as nameForm_nameField
and by the validation rules, as you can see in the example.
To print errors you can add in your layout:
<div id="nameForm_nameField_error"></div>
<div id="nameForm_nameField1_error"></div>
/ ...
<div id="nameForm_nameFieldN_error"></div>
The div id must to have the nameForm_nameField
followed by _error
. You have to write one for each field.
Now you can validate your form in real time, but if you like stopping the form if the validation returns errors, add the javascript function in your layout:
$( document ).ready(function() {
$( "#sendForm" ).click(function() {
//list functions, each per field
var c_nameField = check_field('nameValidation', 'nameForm_nameField');
var c_nameField1 = check_field('nameValidation', 'nameForm_nameField1');
//..
var c_nameFieldN = check_field('nameValidation', 'nameForm_nameFieldN');
//if you have a radio or checkbox
var c_nameFieldToCheck = check_field_check('nameValidation', 'nameFieldToCheck');
if( c_nameField == 1 && c_nameField1 == 1 )
{
var form_data = $('#myForm').serialize();
$.ajax({
url: Routing.generate('_your_route_to_save_form'),
type: "POST",
data: form_data,
dataType: "html",
async : false,
success: function(msg) {
//if the function have no error return 1
if(msg == 1){
alert('Saved');
}else{
check_field('nameValidation', 'nameForm_nameField');
check_field('nameValidation', 'nameForm_nameField1');
//...
check_field('nameValidation', 'nameForm_nameFieldN');
}
},
error: function(){
alert("ERROR!");
}
});
}
});
});
This is just an example, you can write your own function.
EqualTo
NotEqualTo
IdenticalTo
NotIdenticalTo
LessThan
LessThanOrEqual
GreaterThan
GreaterThanOrEqual
...