简体   繁体   中英

Symfony2 autogenerated HTML5 constraints does not work

I'm trying to create a form with Symfony2 (v2.3.6) and take advantage of the autogenerated HTML5 constraints.

So, I created a very simple form with just one field with a RegEx constraint:

public function formAction()
{
    $form = $this->createFormBuilder()->add('animalName', 'text', array(
        'constraints' => new \Symfony\Component\Validator\Constraints\Regex('/(cat|dog)/')
    ))->getForm();

    if ($this->getRequest()->isMethod('POST')) {
        $form->bind($this->getRequest());
    }

    return $this->render('MeTestBundle:Default:form.html.twig', array('form' => $form->createView()));
}

And, in Twig, nothing out of the ordinary.

{% extends "::base.html.twig" %}

{% block body %}
    {{ form(form) }}
{% endblock %}

Well, as a final result, I was expecting animalName field to has a pattern attribute with value (cat|dog) . As it says in this link , Symfony would generate the htmlPattern of this constraint (I tested it, it returns .*(cat|dog).* , which is ok), and this attribute would be used on client side validation by using pattern HTML attribute on the input element. But there is no pattern attribute, the generated code is as follows:

<input type="text" id="form_animalName" name="form[animalName]" required="required" />

After a little research, I think that the responsible of guess the value of pattern attribute is Symfony\\Component\\Form\\Extension\\Validator\\ValidatorTypeGuesser , but this service is never initialized (I wrote a die in it constructor and also forced the container to get the service to check if die is reached).

Am I missing something?

can you try the following code:

   $form = $this->createFormBuilder()
            ->add('animalName', 'text', array(
                'pattern' => '/(cat|dog)/'
            ))
            ->getForm();

Rendered HTML I got:

<div id="form">
<div><label for="form_animalName" class="required">Animal name</label>
<input type="text" id="form_animalName" name="form[animalName]" required="required" pattern="/(cat|dog)/">
</div>
<input type="hidden" id="form__token" name="form[_token]" value="kAg4Ww2oH9WQX6fPSyvJd4pNx-xE7B4G0NbIXtUWWDY">
</div>

I got the answer from: https://github.com/symfony/symfony/issues/3766 Please look into it for more information.

While looking to resolve the issue myself, I came across this question, albeit old, I figured I'd post my findings for any others looking as to why.

Looking at the Symfony source code, the pattern , and other HTML5 validations are only added through the guessers and are only called under createBuilderForProperty , used only when the builder property type is NULL source code and the data_class is specified. It appears to be persistent from 2.0 to 3.4 - I did not look into 4.x.

To resolve the issue, you would need to exclude the explicit type and specify a data_class model that holds the desired constraint validations. Then Symfony will use the guessers to determine the type and attributes to add to the HTML5 elements.

Form Builder

$form = $this->createFormBuilder(null, ['data_class' => AnimalModel::class])
    ->add('animalName')
    ->getForm();

Data Class Model

use Symfony\Component\Validator\Constraints as Assert;

class AnimalModel
{

    /**
     * @Assert\Regex(pattern="/(cat|dog)/")
     */
    private $animalName;

    public function getAnimalName()
    {
        return $this->animalName;
    }

    public function setAnimalName($name)
    {
        $this->animalName = $name;

        return $this->animalName;
    }
}

Result

<!-- {{ form(form) }} -->
<input type="text" id="form_animalName" name="form[animalName]" pattern=".*((cat|dog)).*">

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM