phpzend-framework2zend-form2

ZF2 Render Custom Class on Form Validation Error


How can I wrap a fieldset tag around my form rows, and how can I add a has-danger class to the fieldset when an element fail to validate?

I think I need to create a viewhelper, check if a specific formelement has a validation message and wrap the row with a fieldset, but I'm not sure if that's the right approach or how to do it.

The output I want on validation error:

<fieldset class="has-danger"><label for="username">Username</label>
<input type="text" name="username" id="username" class="form-control 
input-error" value="f"><ul><li>Needs to be    5-20 characters long</li>
</ul></fieldset>

register.phtml:

<?php
$form = $this->registerForm;
$form->prepare();
echo $this->form()->openTag($form);

echo $this->formHidden($form->get('secret'));
echo $this->formRow($form->get('username'));
echo $this->formRow($form->get('password'));
echo $this->formRow($form->get('email'));
echo $this->formRow($form->get('confirm-email'));
echo $this->formSubmit($form->get('submit'));
echo $this->form()->closeTag($form);

Solution

  • Ok, you should use the formLabel(), formElement() and formElementErrors() view helpers instead of formRow().

    To my ZF2 knowledge, the formRow() view helper doesn't let you have control on the HTML output easily. It displays the complete input HTML (label + input + errors) in one line of code.

    To simply achieve your goal, your phtml structure for one input has to be as follow :

    // NAME_OF_YOUR_FILE.phtml
    <?php
        $userNameInput       = $form->get('username');
        $userNameInputErrors = $this->formElementErrors($userNameInput);
    ?>
    <fieldset class="<?= $userNameInputErrors ? 'has-danger' : '' ?>" >
        <?= $this->formLabel($userNameInput) ?>
        <?= $this->formElement($userNameInput) ?>
        <?= $userNameInputErrors ?>
    </fieldset>
    

    This is a hard work to do this for each fields in form, so I suggest you to put this logic in a view helper.

    // MyFormRow.php 
    <?php
        namespace Your\Namespace;
    
        use Zend\View\Helper\AbstractHelper;
    
        class MyFormRow extends AbstractHelper
        {
            protected $formLabelViewHelper;
            protected $formElementViewHelper;
            protected $formElementErrorsViewHelper;
    
            public function __construct($formLabelViewHelper, $formElementViewHelper, $formElementErrorsViewHelper)
            {
                $this->formLabelViewHelper         = $formLabelViewHelper;
                $this->formElementViewHelper       = $formElementViewHelper;
                $this->formElementErrorsViewHelper = $formElementErrorsViewHelper;
            }
    
            public function __invoke($formElement)
            {
                 $html = '';
    
                 $errors = $this->formElementErrorsViewHelper->__invoke($formElement);     
    
                 $html .= '<fieldset class=" . ($errors ? 'has-danger' : '') . ">';    
                     $html .= $this->formLabelViewHelper->__invoke($formElement); 
                     $html .= $this->formElementViewHelper->__invoke($formElement);  
                     $html .= $errors;   
                 $html .= '</fieldset>';
    
                 return $html;
            }
        }
    ?>
    

    Declare it in your Module.php.

    // In your Module.php
    <?php
    
        ...
    
        public function getViewHelperConfig()
        {
            return [
                'factories'  => [
                    'myFormRow' => function (HelperPluginManager $helperPluginManager) {
                        $formLabelViewHelper        = $helperPluginManager->get('formLabel');
                        $formElementViewHelper      = $helperPluginManager->get('formElement');
                        $formElementErrorsViewHelper = $helperPluginManager->get('formElementErrors');
    
                        return new MyFormRow($formLabelViewHelper, $formElementViewHelper, $formElementErrorsViewHelper);
                    },
                ],
            ];
        }
    ?>
    

    And now in your phtml file, simply :

    // NAME_OF_YOUR_FILE.phtml
    
    ...
    
    <?= echo $this->myFormRow($form->get('username')) ?>
    
    ...