Symfony2: How to use constraints on custom compound form type?

Maurice

Here is a question I've been breaking my head over for a while now. Please know that I'm not a Symfony2 expert (yet), so I might have made a rookie mistake somewhere.

Field1: Standard Symfony2 text field type

Field2: Custom field type compoundfield with text field + checkbox field)

preview

My Goal: Getting constraints added to the autoValue field to work on the autoValue's text input child

The reason why the constraints don't work is probably because NotBlank is expecting a string value and the internal data of this form field is an array array('input'=>'value', 'checkbox' => true). This array value gets transformed back into a string with a custom DataTransformer. I suspect however that that happens AFTER validating the field against known constraints.

As you see below in commented code, I have been able to get constraints working on the text input, however only when hardcoded into the autoValue's form type, and I want to validate against the main field's constraints.

My (simplified) sample code for controller and field:

.

Controller code

Setting up a quick form for testing purposes.

<?php
//...
// $entityInstance holds an entity that has it's own constraints 
// that have been added via annotations

$formBuilder = $this->createFormBuilder( $entityInstance, array(
    'attr' => array(
        // added to disable html5 validation
        'novalidate' => 'novalidate'
    )
));

$formBuilder->add('regular_text', 'text', array(
    'constraints' => array(
        new \Symfony\Component\Validator\Constraints\NotBlank()
    )
));

$formBuilder->add('auto_text', 'textWithAutoValue', array(
    'constraints' => array(
        new \Symfony\Component\Validator\Constraints\NotBlank()
    )
));

.

TextWithAutoValue source files

src/My/Component/Form/Type/TextWithAutoValueType.php

<?php

namespace My\Component\Form\Type;

use My\Component\Form\DataTransformer\TextWithAutoValueTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class TextWithAutoValueType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('value', 'text', array(
            // when I uncomment this, the NotBlank constraint works. I just
            // want to validate against whatever constraints are added to the
            // main form field 'auto_text' instead of hardcoding them here
            // 'constraints' => array(
            //     new \Symfony\Component\Validator\Constraints\NotBlank()
            // )
        ));

        $builder->add('checkbox', 'checkbox', array(
        ));

        $builder->addModelTransformer(
            new TextWithAutoValueTransformer()
        );
    }

    public function getName()
    {
        return 'textWithAutoValue';
    }
}

src/My/Component/Form/DataTransformer/TextWithAutoValueType.php

<?php

namespace My\Component\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;

class TextWithAutoValueTransformer 
    implements DataTransformerInterface
{
    /**
     * @inheritdoc
     */
    public function transform($value)
    {
        return array(
            'value'    => (string) $value,
            'checkbox' => true
        );
    }

    /**
     * @inheritdoc
     */
    public function reverseTransform($value)
    {
        return $value['value'];
    }
}

src/My/ComponentBundle/Resources/config/services.yml

parameters:

services:
    my_component.form.type.textWithAutoValue:
        class: My\Component\Form\Type\TextWithAutoValueType
        tags:
            - { name: form.type, alias: textWithAutoValue }

src/My/ComponentBundle/Resources/views/Form/fields.html.twig

{% block textWithAutoValue_widget %}
    {% spaceless %}

    {{ form_widget(form.value) }}
    {{ form_widget(form.checkbox) }}
    <label for="{{ form.checkbox.vars.id}}">use default value</label>

    {% endspaceless %}
{% endblock %}

.

Question

I have been reading docs and google for quite some hours now and can't figure out how to copy, bind, or reference the original constraints that have been added while building this form.

-> Does anyone know how to accomplish this?

-> For bonus points; how to enable the constraints that have been added to the main form's bound entity? (via annotations on the entity class)

PS

Sorry it became such a long question, I hope that I succeeded in making my issue clear. If not, please ask me for more details!

Zephyr

I suggest you read again the documentation about validation first.

What we can make out of this is that validation primarily occurs on classes rather than form types. That is what you overlooked. What you need to do is:

  • To create a data class for your TextWithAutoValueType, called src/My/Bundle/Form/Model/TextWithAutoValue for instance. It must contain properties called text and checkbox and their setters/getters;
  • To associate this data class to your form type. For this, you must create a TextWithAutoValueType::getDefaultOptions() method and populate the data_class option. Go here for more info about this method;
  • Create validation for your data class. You can either use annotations or a Resources/config/validation.yml file for this. Instead of associating your constraints to the fields of your form, you must associate them to the properties of your class:

validation.yml:

src/My/Bundle/Form/Model/TextWithAutoValue:
    properties:
        text:
            - Type:
                type: string
            - NotBlank: ~
        checkbox:
            - Type:
                type: boolean

Edit:

I assume that you already know how to use a form type in another. When defining your validation configuration, you can use a very useful something, called validation groups. Here a basic example (in a validation.yml file, since I'm not much proficient with validation annotations):

src/My/Bundle/Form/Model/TextWithAutoValue:
    properties:
        text:
            - Type:
                type: string
                groups: [ Default, Create, Edit ]
            - NotBlank:
                groups: [ Edit ]
        checkbox:
            - Type:
                type: boolean

There is a groups parameter that can be added to every constraint. It is an array containing validation group names. When requesting a validation on an object, you can specify with which set of groups you want to validate. The system will then look in the validation file what constraints should be applied.

By default, the "Default" group is set on all constraints. This also is the group that is used when performing a regular validation.

  • You can specify the default groups of a specific form type in MyFormType::getDefaultOptions(), by setting the validation_groups parameter (an array of strings - names of validation groups),
  • When appending a form type to another, in MyFormType::buildForm(), you can use specific validation groups.

This, of course, is the standard behaviour for all form type options. An example:

$formBuilder->add('auto_text', 'textWithAutoValue', array(
    'label' => 'my_label',
    'validation_groups' => array('Default', 'Edit'),
));

As for the use of different entities, you can pile up your data classes following the same architecture than your piled-up forms. In the example above, a form type using textWithAutoValueType will have to have a data_class that has a 'auto_text' property and the corresponding getter/setter.

In the validation file, the Valid constraints will be able to cascade validation. A property with Valid will detect the class of the property and will try to find a corresponding validation configuration for this class, and apply it with the same validation groups:

src/My/Bundle/Form/Model/ContainerDataClass:
    properties:
        auto_text:
            Valid: ~ # Will call the validation conf just below with the same groups

src/My/Bundle/Form/Model/TextWithAutoValue:
    properties:
        ... etc

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Symfony2: How to use constraints on custom compound form type?

From Dev

Symfony2 Custom Form Type or Extension

From Dev

Symfony2 use doctrine in form type

From Dev

Symfony2 - Creating a template for a custom form type

From Dev

Symfony2 Custom Field Type and Form Events on Submit

From Dev

Use a custom constraint/validator in symfony form type

From Dev

Use a custom constraint/validator in symfony form type

From Dev

How to create a custom Symfony2 Twig form template block

From Dev

Symfony2 - How to validate autocomplete entity form type?

From Dev

How to use an array as choices for "choice" in form builder symfony2

From Dev

Symfony2 Forms - How to use parametrized constructors in form builders

From Dev

How to use Symfony2 form elements individually?

From Dev

Symfony2 - createForm called with custom form type's name/alias throws "Could not load type" exception

From Dev

symfony2 rendering of a form as form type

From Dev

How to create and use a form in a custom class in Symfony 2

From Dev

Symfony2 Custom Form Field Type HTML5 color

From Dev

Symfony2 Form Type - how to set form CSS class as attribute?

From Dev

Symfony2 Container Aware Form Type

From Dev

form type mapped false symfony2

From Dev

Symfony2 Container Aware Form Type

From Dev

How to add VueJS's v-model attribute into Symfony2 form type

From Dev

symfony2 - How to create a form field of type "entity" without values

From Dev

How to add VueJS's v-model attribute into Symfony2 form type

From Dev

symfony custom form type with assets

From Dev

symfony2 / twig : how to use include in a block used in a form theme?

From Dev

How to submit form ajax in symfony2?

From Dev

how to style a symfony2 form button

From Dev

How to set form name in Symfony2?

From Dev

How to name a form in symfony2?

Related Related

  1. 1

    Symfony2: How to use constraints on custom compound form type?

  2. 2

    Symfony2 Custom Form Type or Extension

  3. 3

    Symfony2 use doctrine in form type

  4. 4

    Symfony2 - Creating a template for a custom form type

  5. 5

    Symfony2 Custom Field Type and Form Events on Submit

  6. 6

    Use a custom constraint/validator in symfony form type

  7. 7

    Use a custom constraint/validator in symfony form type

  8. 8

    How to create a custom Symfony2 Twig form template block

  9. 9

    Symfony2 - How to validate autocomplete entity form type?

  10. 10

    How to use an array as choices for "choice" in form builder symfony2

  11. 11

    Symfony2 Forms - How to use parametrized constructors in form builders

  12. 12

    How to use Symfony2 form elements individually?

  13. 13

    Symfony2 - createForm called with custom form type's name/alias throws "Could not load type" exception

  14. 14

    symfony2 rendering of a form as form type

  15. 15

    How to create and use a form in a custom class in Symfony 2

  16. 16

    Symfony2 Custom Form Field Type HTML5 color

  17. 17

    Symfony2 Form Type - how to set form CSS class as attribute?

  18. 18

    Symfony2 Container Aware Form Type

  19. 19

    form type mapped false symfony2

  20. 20

    Symfony2 Container Aware Form Type

  21. 21

    How to add VueJS's v-model attribute into Symfony2 form type

  22. 22

    symfony2 - How to create a form field of type "entity" without values

  23. 23

    How to add VueJS's v-model attribute into Symfony2 form type

  24. 24

    symfony custom form type with assets

  25. 25

    symfony2 / twig : how to use include in a block used in a form theme?

  26. 26

    How to submit form ajax in symfony2?

  27. 27

    how to style a symfony2 form button

  28. 28

    How to set form name in Symfony2?

  29. 29

    How to name a form in symfony2?

HotTag

Archive