3

I created a Custom Constraint ( with help from cookbook ). Everything seems to work as i expected, but now I would like to show the error-message not beneath validated-field but at the top of the form (like general form-errors)

My Constraint Class:

class NotOverlapPreviousRecord extends Constraint
{
    //@todo
    public $message = '{{ value }} is invalid!';

    public function validatedBy()
    {
        return 'not_overlap_previous_record';
    }

    public function getTargets()
    {
        return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
    }
}

and its validator class

class NotOverlapPreviousRecordValidator extends ConstraintValidator
{
    /**
     * @var EntityManager
     */
    private $em;

    public function __construct(EntityManager $o_entitymanager)
    {
        $this->em = $o_entitymanager;
    }

    public function validate($value, Constraint $constraint)
    {
        /** just for demonstration & testing purpose */
        if (true) {
            $this->context->buildViolation($constraint->message)
                ->setParameter('{{ value }}', $value )
                ->addViolation();
        }
    }
}

and the FormType where I use custom constraint:

class QuickTimepatchForm extends AbstractType {

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('timeStart', 'time',
                    array('label' => 'forms.timepatching.label.starttime',
                          'html5' => true,
                          'widget' => 'single_text',
                          'consatraints' => array(
                              // MY CUSTOM CONSTRAINT. WORKS WELL, but since a use it on 'timeStart', the error message is also beneath the timeStart field...
                              new TmAssert\NotOverlapPreviousRecord()
                          )));
        /** ... other fields .... */
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        /** ... stuff ... */
    }

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

So my question is: Is there a way to somehow modify validate() method of NotOverlapPreviousRecordValidator so the error message appears on top of the form and not beneath its field ? If not, is there any other way to achieve my goals ?

IMPORTANT! I do not want (I should not) use this custom Constraint as Annotation. No @TmAssert\NotOverlapPreviousRecord in my Entity.

Now I have this:
enter image description here
which is ok, but i want this:
enter image description here

UPDATE: My current form-twig-tempalte:

{#   SETUP!   #}
{% form_theme o_form 'bootstrap_3_horizontal_layout.html.twig' %}

{#  THE FORM  #}
{{ form_start(o_form, {'attr' : {'class' : 'tm-patching-form-inline'}}) }}
<fieldset>
    {{ form_errors(o_form) }}
    <legend class="tm-{{ o_form.vars.value.getTimetick.getState }}">{{ o_form.vars.value.getTimetick.getState|trans }} :: TIMEPATCH</legend>
    <div class="form-group col-lg-9">
        <div class="col-lg-6 {% if not o_form.timeStart.vars.valid -%}has-error{%- endif %}">
            {{ form_label(o_form.timeStart) }}
            {{ form_widget(o_form.timeStart, {'attr' : {'class' : 'tm-timepatch-start'}}) }}
            {{ form_errors(o_form.timeStart) }}
        </div>
        <div class="col-lg-6 {% if not o_form.timeEnd.vars.valid -%}has-error{%- endif %}">
            {{ form_label(o_form.timeEnd) }}
            {{ form_widget(o_form.timeEnd, {'attr' : {'class' : 'tm-timepatch-end'}}) }}
            {{ form_errors(o_form.timeEnd) }}
        </div>
        <div class="col-lg-12 {% if not o_form.note.vars.valid -%}has-error{%- endif %}">
            {{ form_label(o_form.note) }}
            {{ form_widget(o_form.note, {'attr': {'class' : 'tm-timepatch-note', 'rows': 4 }}) }}
            {{ form_errors(o_form.note) }}
        </div>
    </div>
    <div class="form-group col-lg-3">
        <label for="{{ o_form.submit.vars.id }}">&nbsp;</label>
        {{ form_row(o_form.submit, {'attr':{'class':'btn-default tm-action-timepatch'}}) }}
    </div>
</fieldset>
{{ form_end(o_form) }}<!-- /.tm-patching-form-inline -->

UPDATE_2: My Goal is to put the error-message from that particular consraint. Not from all other. Only errors from NotOverlapPreviousRecord should be "moved" to {{form_errors(o_form)}} block. All other Validators/Constraints should work as usual

V-Light
  • 3,065
  • 3
  • 25
  • 31

2 Answers2

1

In your form type class you can add an event listener to your form builder that will listen for FormEvents::POST_SUBMIT event and in that listener you can check if the form has errors, select the one that is from your NotOverlapPreviousRecord constraint and add a flash message in session with info about this error. At the top of your form you will check for this kind of flashes and display them.

It's not the perfect solution, but it must work

Alexandru Furculita
  • 1,374
  • 9
  • 19
0

You need to do two things:

  • Create a custom twig file to render your form, and remove the form display errors, so the field will not display the errors but still mark them as invalid.
  • Modify the form rendering block or add the {{ form_errors(form) }} at the begining of the form.

Here is some doc talking about that: Customize Forms

Ramy Deeb
  • 583
  • 6
  • 15
  • I already did this before... (I'll update my question and add twig-code) The problem ist not HOW TO DISPLAY form errors, the proble is How to set the error-message to a form from a field – V-Light Jan 25 '15 at 19:43
  • Forms in symfony can't store errors, widgets are the ones that can be validated and have the errors, by printing all the form errors at the top of the form, and disabling the error description in the field, you can achieve exactly what you want. – Ramy Deeb Jan 25 '15 at 19:50
  • I added twig-template to a question. Take a look – V-Light Jan 25 '15 at 19:53
  • Check this answer: http://stackoverflow.com/a/20613134/935996 and remove the form_errors(o_form.child) – Ramy Deeb Jan 25 '15 at 19:57
  • thanks, but i think you've slightly misunderstood me. I'd like to put errors to a `form_errors` block **only** from my custom constraint. All other Validators/Constrains, which are defined in the Entity, should work as usual and appear beneath properties they are assigned to – V-Light Jan 26 '15 at 16:56