clicktrend/frontend-validation-bundle
Installation
composer require clicktrend/frontend-validation-bundle:dev-master
Register the bundle in app/AppKernel.php:
new Clicktrend\Bundle\FrontendValidationBundle\ClicktrendFrontendValidationBundle(),
Configure Assetic
Add to app/config/config.yml:
assetic:
assets:
jquery_validation:
inputs:
- "%kernel.root_dir%/../vendor/reactive-raven/jq-bootstrap-validation/src/jqBootstrapValidation.js"
output: js/jqBootstrapValidation.js
Include the generated JS in your layout:
{% block javascripts %}
{{ parent() }}
{{ asset('js/jqBootstrapValidation.js') }}
{% endblock %}
First Use Case
Annotate a form field in an entity (e.g., User.php):
use Symfony\Component\Validator\Constraints as Assert;
class User
{
/**
* @Assert\NotBlank(groups={"registration"})
* @Assert\Email(groups={"registration"})
*/
protected $email;
}
Render the form with novalidate and form-horizontal classes:
<form class="form-horizontal" action="{{ path('registration') }}" method="POST" novalidate>
{{ form_row(form.email) }}
<button type="submit">Submit</button>
</form>
Entity Annotations
Use Symfony’s validation constraints (NotBlank, Email, Length, Regex) on entity properties. Group constraints by logical steps (e.g., registration, profile_update):
/**
* @Assert\Length(
* min=8,
* max=32,
* groups={"registration", "profile_update"}
* )
*/
protected $password;
Form Type Configuration
Extend AbstractType to bind validation groups dynamically:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'validation_groups' => function (Options $options) {
return ['registration']; // Default group
},
]);
}
Override groups per action in the controller:
$form = $this->createForm(UserType::class, $user, [
'validation_groups' => ['profile_update'],
]);
Frontend Integration Ensure forms include:
class="form-horizontal" (for Bootstrap styling).novalidate (to disable HTML5 validation).data-validation-groups (to pass validation groups to JS):
<form class="form-horizontal" novalidate data-validation-groups="{{ form.validation_groups|json_encode }}">
JavaScript Initialization Initialize validation on form submission:
$(document).ready(function() {
$('form').jqBootstrapValidation({
validationGroups: $('form').data('validation-groups'),
preventSubmit: true,
submitError: function($form, event, errors) {
// Handle errors (e.g., show messages)
}
});
});
Base Form Type Create a base form type to enforce validation patterns:
abstract class BaseFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
$form->add('submit', SubmitType::class, ['attr' => ['class' => 'btn btn-primary']]);
});
}
}
Dynamic Validation Groups Use a service to resolve groups based on route parameters:
# services.yml
services:
app.validation_group_resolver:
class: App\Service\ValidationGroupResolver
arguments: ['@router']
// ValidationGroupResolver.php
public function resolve(string $routeName): array
{
if ($routeName === 'registration') {
return ['registration'];
}
return ['default'];
}
Custom Error Rendering Override Twig’s error rendering to integrate with Bootstrap:
{% macro renderErrors(form) %}
{% for error in form.errors %}
<div class="alert alert-danger">{{ error.message }}</div>
{% endfor %}
{% endmacro %}
Missing Validation Groups
data-validation-groups is omitted.data-validation-groups="{{ form.validation_groups|json_encode }}".jqBootstrapValidation errors (e.g., ValidationGroups not defined).Constraint Mismatch
Email, Length, NotBlank, and Regex are supported. Other constraints (e.g., Unique) are ignored.Assetic Asset Paths
jqBootstrapValidation.js may not generate if Assetic is misconfigured.inputs path in config.yml matches the vendor structure. For debugging, manually include the JS:
{{ asset('vendor/reactive-raven/jq-bootstrap-validation/src/jqBootstrapValidation.js') }}
Bootstrap CSS Dependency
bootstrap.css is loaded before jqBootstrapValidation.js.Console Logs Add debug logs to the JS initialization:
console.log('Validation groups:', $('form').data('validation-groups'));
Symfony Validator Test backend validation first:
$errors = $validator->validate($entity, ['registration']);
dump($errors); // Check for constraint issues
Bundle Overrides
If extending the bundle, override the ClicktrendFrontendValidationBundle class and redefine the loadConstraints method to support additional constraints.
Add Custom Constraints
Extend the bundle’s constraint mapper (located in DependencyInjection/ClicktrendFrontendValidationExtension.php) to support more constraints:
// Example: Add 'Unique' constraint
$constraints['Unique'] = [
'field' => 'unique',
'message' => 'form.unique',
];
Custom Validation Messages
Override translation keys in config.yml:
twig:
globals:
form_errors:
form.username.min_length: "Username must be at least 4 characters."
Event Listeners
Listen to form.submit to trigger validation manually:
$('form').on('submit', function() {
if (!$(this).jqBootstrapValidation('isValid')) {
return false; // Prevent submission
}
});
Integration with Symfony Forms
Use the form_errors Twig function to render errors dynamically:
{% for error in form_errors(form.email) %}
<div class="text-danger">{{ error.message }}</div>
{% endfor %}
How can I help you explore Laravel packages today?