phpzend-framework2zend-form2

Zend framework 2 - make form fields sticky when there is error submitting form


I am working on Zend framework 2. I have one form for saving shop information. I have validated the form using Zend's input filters. My issue is when I enter wrong data into the field or keep a mandatory field blank then it properly displays the error but entire form gets blank again.

I want the previously entered values as it is when the form shows errors.

Following is the function that renders the form.

public function settingsAction()
{
        try {

            $message = '';
            $error = '';
            $id = 0;
            try {
                $shop = $this->_getShop();
            } catch (\Exception $ex) {
                AppLogger::log($ex);
                $error = $ex->getMessage();
            }
            if ($shop) {
                $id = $shop->id;
            }
            else {
                //redirect to login page
                return $this->redirect()->toUrl($this->_getDomainUrl());
            }

            $form = new ShopForm($this->serviceLocator);
            $config = $this->serviceLocator->get('config');
            $apiUrls = $config['apiUrls'];

            $request = $this->getRequest();
            if ($request->isPost()) 
            {
                if (!$shop)
                    $shop = new Shop();
                $form->setInputFilter($shop->getInputFilter());
                $form->setData($request->getPost());

                if ($form->isValid()) {
                    $url = $shop->url;
                    $token = $shop->token;
                    $config_id = $shop->config_id;
                    $password = $shop->password;
                    $shop->exchangeArray($form->getData(),false);
                    $shop->url = $url;
                    $shop->token = $token;
                    $shop->config_id = $config_id;
                    DAL::getShopTable($this->serviceLocator)->saveShop($shop);
                    $message = "Your settings has been saved successfully.";
                }
                else {
                    $error = 'There are values that need to be completed before you can save/update your preferences.';

                   foreach($form->getMessages() as $msg) {
                        $error = $error . $msg;
                    }
                }
            }

            if ($shop) 
            {
                echo "<pre>";print_r($shop);
                $shop->selected_countries = unserialize($shop->selected_countries);
                $form->bind($shop);
                $form->get('return_address_country')->setAttribute('value', $shop->return_address_country);
            }

            $form->get('submit')->setAttribute('value', 'Save');
            return array(
                'id' => $id,
                'form' => $form,
                'apiUrls' => $apiUrls,
                'message' => $message,
                'uri' => $this->_selfURL(),
                "error" => $error

            );
        }
        catch (\Exception $ex) {
            AppLogger::log($ex);
            throw $ex;
        }
    }

I have used $form->setInputFilter($shop->getInputFilter()); for validations. A snippet from getInputFilter() is as follows:

public function getInputFilter()
    {
        if (!$this->inputFilter) {
            $inputFilter = new InputFilter();

            $inputFilter->add(array(
                'name' => 'id',
                'required' => true,
                'filters' => array(
                    array('name' => 'Int'),
                ),
            ));
            $inputFilter->add(array(
                'name' => 'ship_to_code',
                'required' => false,
                'filters' => array(
                    array('name' => 'StripTags'),
                    array('name' => 'StringTrim'),
                ),
                'validators' => array(
                    array(
                        'name' => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min' => 0,
                            'max' => 50,
                        ),
                    ),
                ),
            ));
            $inputFilter->add(array(
                'name' => 'default_phone',
                'required' => false,
                'filters' => array(
                    array('name' => 'StripTags'),
                    array('name' => 'StringTrim'),
                ),
                'validators' => array(
                    array(
                        'name' => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min' => 0,
                            'max' => 50,
                        ),
                    ),
                ),
            ));
            $inputFilter->add(array(
                'name' => 'max_records_per_file',
                'required' => true,
                'filters' => array(
                    array('name' => 'Int'),
                ),
            ));
    }

And the form is

$this->add(array(
        'name' => 'id',
        'type' => 'Hidden',
    ));
    $this->add(array(
        'name' => 'ship_to_code',
        'type' => 'Text',
        'options' => array(
            'label' => 'Ship-To Code',
        ),
    ));
    $this->add(array(
        'name' => 'default_phone',
        'type' => 'Text',
        'options' => array(
            'label' => 'Default Phone',
        ),
    ));

Solution

  • You can use the setdata() method of form in your setting action. Here's updated code

     if ($shop) 
                {
                  //  echo "<pre>";print_r($shop);
                  //  $shop->selected_countries = unserialize($shop->selected_countries);
                    $form->bind($shop);
                    $form->setData($request->getPost()); // set post data to form
                }