We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Form Validation and Messages question

Hi there,

I have a question about Validation and some confusion I have. If you look at this example https://github.com/phalcon/vokuro/blob/master/app/views/session/signup.volt you can see that the Volt template calls form.messages under each and every input element in the form.

I followed this pattern for my own form but when the controller action is initially called, the inputs aren't valid and the message(s) to this effect are displayed on the form. Ideally, I only want to display validation/error messages after the form has been posted (via the submit button) and not when it is initially rendered.

Have I missed something here or was this just a design decision in the vokuro forms?

Any advice appreciated. Thanks.



38.8k

For now, I added a check to the messages method to see if we are in a post:

    public function messages($name)
    {
        if (!$this->request->isPost()) {
            return;
        }

        if ($this->hasMessagesFor($name)) {
            foreach ($this->getMessagesFor($name) as $message) {
                $this->flash->error($message);
            }
        }
    }

This seems to work OK but I'd really appreciate any feedback around my original question. Thanks!



10.9k

From what you have posted it looks like a stripped down version of this kind of thing:

<?php
public function someAction($name)
    {
        if ($this->request->isPost()) // if there is post data 
        {
            //Some code here that saves data to the database and other things

            if ($this->hasMessagesFor($name)) 
            {
                foreach ($this->getMessagesFor($name) as $message) 
                {
                    $this->flash->error($message);
                }
            } 

            else 
            {
                $this->flash->success("Your details were saved!");
            }
        }

        // code to do with view data would sit outside. Messages should not appear if there is no post data.
    }

$this->flash->error($message); tends to be used for getting messages to appear at the top of the page and doesn't relate to the {{ form.messages('name') }} style commands you see in the volt template. I'm having to guess a bit here for you though.



38.8k

@pixiesky yep, I was basing my code on that shown in https://github.com/phalcon/vokuro/blob/master/app/views/session/signup.volt

Is there an alernative approach to associating form input validation errors with the appropriate input element(s)?

Cheers



10.9k
edited Apr '14

I've just had a look: {{ form.messages("name") }} is pulling from $form = new SignUpForm(); looking at the link. If you take a look at the volt layout's controller >> https://github.com/phalcon/vokuro/blob/master/app/controllers/SessionController.php << You will see that the signupAction() creates a $form variable and inserts a new SignUpForm() object in to it.

<?php
/**
     * Allow a user to signup to the system
     */
    public function signupAction()
    {
        $form = new SignUpForm();

        if ($this->request->isPost()) {

            if ($form->isValid($this->request->getPost()) != false) {

                $user = new Users();

                $user->assign(array(
                    'name' => $this->request->getPost('name', 'striptags'),
                    'email' => $this->request->getPost('email'),
                    'password' => $this->security->hash($this->request->getPost('password')),
                    'profilesId' => 2
                ));

                if ($user->save()) {
                    return $this->dispatcher->forward(array(
                        'controller' => 'index',
                        'action' => 'index'
                    ));
                }

                $this->flash->error($user->getMessages());
            }
        }

        $this->view->form = $form;
    }

The form object is then being passed to the volt view via $this->view->form = $form which is why volt can access them via {{ form.messages(THE_FIELD_NAME) }} so I can only imagine that because SignUpForm extends Form that the messages are being created within /Phalcon/Form via . I think, I don't know, I think these messages are being created what $this->getMessagesFor($name) is being called.

See getMessages in https://docs.phalcon.io/en/latest/api/Phalcon_Forms_Form.html

You could check by placing print_r($form); exit; before $this->view->form = $form and use your browser find for 'messages' or even print_r($form->messages); exit; as an experiment.

My guess would be that:

<?php
public function messages($name)
    {
        if ($this->hasMessagesFor($name) && $this->request->isPost()) {
            foreach ($this->getMessagesFor($name) as $message) {
                $this->flash->error($message);
            }
        }
    }

...would be fine to use. If I'm right that is.

            if(is_array($user->getMessages())){
              foreach( $user->getMessages() as $msg ){
                $this->flash->error($msg);
              }
            }else{
              $this->flash->error($user->getMessages());
            }