This bundle is designed to validate Symfony forms on the front-end without duplicating code or validation efforts. This plugin also fully supports translations for error messages and suggestion text.
composer require josephjbrewer/form-utils
// app/AppKernel.php
public function registerBundles()
{
return array(
// ...
new JJB\FormUtilsBundle\JJBFormUtilsBundle(),
);
}
Edit app/config.yml and set the default form template provided by the form-utils bundle.
twig:
form:
resources:
- 'JJBFormUtilsBundle:Form:form_theme.html.twig'
Add the assets provided in this bundle. I recommend using assetic.
{% javascripts
'@JJBFormUtilsBundle/Resources/assets/js/jquery.validator.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
{% stylesheets
'@JJBFormUtilsBundle/Resources/assets/css/style.scss' filter='compass' %}
<link rel="stylesheet" href="{{ asset_url }}"/>
{% endstylesheets %}
By default, the provided form template uses the bootstrap theme provided by Symfony. This can be easily changed by making your own form theme and extending what is provided by this bundle.
The example below uses Symfony's default form theme.
<!-- AppBundle/Resources/views/form-template.html.twig -->
{% extends 'form_div_layout.html.twig' %}
{% use 'JJBFormUtilsBundle:Form:form_blocks.html.twig' %}
In order for the form elements to render the data attributes required for validation, you will need to use twig to render the form fields.
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.username) }}
{{ form_row(form.password) }}
{{ form_row(form.submit) }}
{{ form_end(form) }}
Data suggestions are used to provide information to the user about a form field. For example, if the form is focused on a password field, it might be helpful to show the user what characters are allowed in the password. To do this, you have to add an attribute to your form field called data-suggest
. This can be done in one of two ways.
This method uses the "attr" option in the form builder.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'password',
'password', [
'attr' => [
'data-suggest' => 'Must contain ...'
]
]
);
}
This method adds the attribute directly to the form field.
{{ form_row(form.password.second, { 'attr' : {
'data-suggest' : 'Must contain ...'
}}) }}
Binding the validator to the form sets up listeners on the form and all of its elements. When the blur event is triggered on a form element, the plugin will validate it. When the submit event is triggered on the form, the plugin will validate all of the form elements. If validation fails, event propagation will stop and the form will not be submitted.
var form = $('#myForm');
// Enable validation (optional configuration)
$(form).validator(options);
In some cases, event propagation will be stopped before the validation listeners are triggered. This can happen if other javascript plugins are also listening to the submit event on the form. If this happens, you will need to manually trigger validator on your form. To do this, just use the following syntax:
if ($(form).validator('validate'[, options])) {
// Do something
}
One of the reasons this bundle was developed is to help with binding errors that occur on the server-side to the form elements on the front-end. When validation fails on the server side, an error object is created. To handle AJAX errors on the front-end, return the serialized error object and the plugin will do the rest.
$(form).validator('handleErrors', response[, options]);
Formatting errors and data suggestions is as simple as providing an inline template. The messageTemplate
key is used for errors and the suggestTemplate
key is used for data suggestions.
$(document).ready(function() {
$('#myForm').validator({
messageTemplate: '<i class="fa fa-exclamation-triangle"></i> {{message}}'
});
});
Key | Description | Default Value |
---|---|---|
rootErrorMessage | Prepend root-level error with a title? (e.g. "Your form contains errors") Only works with AJAX errors | null |
continueOnError | Continue validation after an error occurs? | false |
separator | Character used to concatenate form id's. | _ |
suggestTemplate | Template used for data suggestions | {{message}} |
messageTemplate | Template used for error messages | {{message}} |
In a lot of cases, developers will use annotations or yaml/xml files to add constraints to a model. When a form is validated in Symfony, these constraints are validated along with any constraints added to the form.
If you instantiate a form that extends AbstractBaseForm
with MetaDataConstraintService
then the form will add the yaml/xml/annotation constraints to the form object when building the form view.
<?php
namespace ApiBundle\Form\Type;
use JJB\FormUtilsBundle\Form\Type\AbstractBaseForm;
class ExampleType extends AbstractBaseForm
{
// ...
}
<?php
namespace AppBundle\Controller;
class DefaultController
{
public function someAction()
{
$service = $this->get('jjb.form_utils.service.meta_data_constraint');
$form = $this->createForm(new ExampleType($service));
return $this->render('...', [
'form' => $form->createView()
]);
}
}