I'm working on an application with ZF 2.8 and i'm trying to maintains the value of a form in case of user input error.
The old datas of the other fields (type <input>) are "still there" if there is a user input error but for the <select> that is not working and i can't understand why...?!
Here is the code of the controller :
public function addAction() {
$form = new InscriptionForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if ($request->isPost()) {
$inscription = new Inscription();
$form->setInputFilter($inscription->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid() && ($request->getPost('ACTIVITE1') != 0 || $request->getPost('ACTIVITE2') != 0 || $request->getPost('ACTIVITE3') != 0)) {
$data = $form->getData();
$inscription->exchangeArray($data);
$lastId = $this->getInscriptionTable()->saveInscription($inscription);
$sm = $this->getServiceLocator();
$adapter = $sm->get('Zend\Db\Adapter\Adapter');
// code - requests
} else {
$sm = $this->getServiceLocator();
$adapter = $sm->get('Zend\Db\Adapter\Adapter');
$statement = $adapter->query(
"
SELECT *
FROM session
"
);
$results = $statement->execute();
if ($request->getPost('ACTIVITE1') == 0 && $request->getPost('ACTIVITE2') == 0 && $request->getPost('ACTIVITE3') == 0) {
return new ViewModel(array(
'errors' => 'Le formulaire contient une ou plusieurs erreurs : Au moins une activité doit être renseignée.',
'form' => $form,
'sessions' => $results
));
} else {
return new ViewModel(array(
'errors' => 'Le formulaire contient une ou plusieurs erreurs.',
'form' => $form,
'sessions' => $results
));
}
}
}
$sm = $this->getServiceLocator();
$adapter = $sm->get('Zend\Db\Adapter\Adapter');
$statement = $adapter->query(
"
SELECT *
FROM session
"
);
$results = $statement->execute();
return new ViewModel(array(
'form' => $form,
'sessions' => $results
));
}
The model Inscription :
<?php
namespace Inscription\Model;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
use Zend\Validator\StringLength;
use Zend\Validator\NotEmpty;
use Zend\Validator\Date;
use Zend\Validator\Regex;
class Inscription implements InputFilterAwareInterface {
public $id_inscription;
public $dt_inscription;
// i delete some attributes because the post was too long
// from insc_sess
public $activite1;
public $activite2;
public $activite3;
protected $inputFilter;
public function getArrayCopy() {
return get_object_vars($this);
}
public function exchangeArray($data) {
$this->id_inscription = (!empty($data['ID_INSCRIPTION'])) ? $data['ID_INSCRIPTION'] : null;
$this->dt_inscription = (!empty($data['DT_INSCRIPTION'])) ? $data['DT_INSCRIPTION'] : null;
$this->nom_enfant = (!empty($data['NOM_ENFANT'])) ? $data['NOM_ENFANT'] : null;
$this->prenom_enfant = (!empty($data['PRENOM_ENFANT'])) ? $data['PRENOM_ENFANT'] : null;
$this->sexe_enfant = (!empty($data['SEXE_ENFANT'])) ? $data['SEXE_ENFANT'] : null;
$this->dtNaissance_enfant = (!empty($data['DTNAISSANCE_ENFANT'])) ? $data['DTNAISSANCE_ENFANT'] : null;
$this->nom_ecole = (!empty($data['NOM_ECOLE'])) ? $data['NOM_ECOLE'] : null;
$this->resp1 = (!empty($data['RESP1'])) ? $data['RESP1'] : null;
$this->adresse_resp1 = (!empty($data['ADRESSE_RESP1'])) ? $data['ADRESSE_RESP1'] : null;
$this->tel_Resp1 = (!empty($data['TEL_RESP1'])) ? $data['TEL_RESP1'] : null;
$this->mail_Resp1 = (!empty($data['MAIL_RESP1'])) ? $data['MAIL_RESP1'] : null;
$this->resp2 = (!empty($data['RESP2'])) ? $data['RESP2'] : null;
$this->adresse_resp2 = (!empty($data['ADRESSE_RESP2'])) ? $data['ADRESSE_RESP2'] : null;
$this->tel_Resp2 = (!empty($data['TEL_RESP2'])) ? $data['TEL_RESP2'] : null;
$this->mail_Resp2 = (!empty($data['MAIL_RESP2'])) ? $data['MAIL_RESP2'] : null;
$this->activite1 = (!empty($data['ACTIVITE1'])) ? $data['ACTIVITE1'] : null;
$this->activite2 = (!empty($data['ACTIVITE2'])) ? $data['ACTIVITE2'] : null;
$this->activite3 = (!empty($data['ACTIVITE3'])) ? $data['ACTIVITE3'] : null;
$this->autorise1 = (!empty($data['AUTORISE1'])) ? $data['AUTORISE1'] : null;
$this->autorise2 = (!empty($data['AUTORISE2'])) ? $data['AUTORISE2'] : null;
$this->saitNager = (!empty($data['SAITNAGER'])) ? $data['SAITNAGER'] : null;
$this->traitement = (!empty($data['TRAITEMENT'])) ? $data['TRAITEMENT'] : null;
$this->ouiTraitement = (!empty($data['OUITRAITEMENT'])) ? $data['OUITRAITEMENT'] : null;
$this->allergies = (!empty($data['ALLERGIES'])) ? $data['ALLERGIES'] : null;
$this->autresAllergies = (!empty($data['AUTRESALLERGIES'])) ? $data['AUTRESALLERGIES'] : null;
$this->autreSante = (!empty($data['AUTRESSANTE'])) ? $data['AUTRESSANTE'] : null;
$this->coche = (!empty($data['COCHE'])) ? $data['COCHE'] : null;
$this->dateNew = (!empty($data['DTNEW'])) ? $data['DTNEW'] : null;
$this->utilNew = (!empty($data['UTILNEW'])) ? $data['UTILNEW'] : null;
$this->dateMAJ = (!empty($data['DTMAJ'])) ? $data['DTMAJ'] : null;
$this->utilMAJ = (!empty($data['UTILMAJ'])) ? $data['UTILMAJ'] : null;
}
public function setInputFilter(InputFilterInterface $inputFilter) {
throw new \Exception("Not used");
}
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$inputFilter->add(array(
'name' => 'DTNAISSANCE_ENFANT',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array(
'messages' => array(
NotEmpty::IS_EMPTY => "Champ obligatoire"
)
)
),
),
));
$inputFilter->add(array(
'name' => 'SAITNAGER',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array(
'messages' => array(
NotEmpty::IS_EMPTY => "Champ obligatoire"
)
)
),
),
));
$inputFilter->add(array(
'name' => 'TRAITEMENT',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array(
'messages' => array(
NotEmpty::IS_EMPTY => "Champ obligatoire"
)
)
),
),
));
$inputFilter->add(array(
'name' => 'COCHE',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array(
'messages' => array(
NotEmpty::IS_EMPTY => "Champ obligatoire"
)
)
),
),
));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
The InscriptionForm class :
<?php
namespace Inscription\Form;
use Zend\Form\Form;
use Zend\Form\Element;
use Zend\Form\Element\Date;
class InscriptionForm extends Form {
public function __construct($name = null) {
parent::__construct('inscription');
$this->add(array(
'name' => 'ID_INSCRIPTION',
'type' => 'hidden',
'required' => 'required'
));
$this->add(array(
'name' => 'NOM_ENFANT',
'type' => 'Text',
'required' => 'required',
'options' => array(
'label' => ' * Nom :',
),
'attributes' => array(
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'PRENOM_ENFANT',
'type' => 'Text',
'required' => 'required',
'options' => array(
'label' => '* Prénom :',
),
'attributes' => array(
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'SEXE_ENFANT',
'type' => 'Zend\Form\Element\Radio',
'required' => 'required',
'options' => array(
'label' => '* Sexe :',
'value_options' => array(
'F' => 'Fille',
'G' => 'Garçon',
),
),
'attributes' => array(
)
));
$this->add(array(
'name' => 'DTNAISSANCE_ENFANT',
'type' => 'Text',
'required' => 'required',
'options' => array(
'label' => '* Date de naissance :',
),
'attributes' => array(
'class' => 'form-control date-field',
'id' => 'input-dtNaissance',
'placeholder' => 'jj/mm/AAAA',
'pattern' => '^([0-2][0-9]|(3)[0-1])(\/)(((0)[0-9])|((1)[0-2]))(\/)\d{4}$'
)
));
$this->add(array(
'name' => 'NOM_ECOLE',
'type' => 'Text',
'required' => 'required',
'options' => array(
'label' => '* Nom de l\'école :',
),
'attributes' => array(
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'ACTIVITE1',
'type' => 'Zend\Form\Element\Select',
'options' => array(
'value_options' => array(
'Choisir l\'activité'
),
'disable_inarray_validator' => true,
),
'attributes' => array(
'class' => 'form-control',
'id' => 'select-session1'
)
));
$this->add(array(
'name' => 'ACTIVITE2',
'type' => 'Zend\Form\Element\Select',
'options' => array(
'value_options' => array(
'Choisir l\'activité'
),
'disable_inarray_validator' => true,
),
'attributes' => array(
'class' => 'form-control',
'id' => 'select-session2'
)
));
$this->add(array(
'name' => 'ACTIVITE3',
'type' => 'Zend\Form\Element\Select',
'options' => array(
'value_options' => array(
'Choisir l\'activité'
),
'disable_inarray_validator' => true,
),
'attributes' => array(
'class' => 'form-control',
'id' => 'select-session3'
)
));
$this->add(array(
'name' => 'RESP1',
'type' => 'Text',
'required' => 'required',
'options' => array(
'label' => '* Nom, prénom Responsable 1:',
),
'attributes' => array(
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'ADRESSE_RESP1',
'type' => 'Text',
'required' => 'required',
'options' => array(
'label' => '* Adresse Responsable 1:',
),
'attributes' => array(
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'TEL_RESP1',
'type' => 'Text',
'options' => array(
'label' => '* Téléphone Responsable 1:',
),
'attributes' => array(
'pattern' => '^0[1-78]([-. ]?[0-9]{2}){4}$',
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'MAIL_RESP1',
'type' => 'Zend\Form\Element\Email',
'options' => array(
'label' => '* Mail Responsable 1:',
),
'attributes' => array(
'class' => 'form-control'
)
));
$this->add(array(
'name' => 'RESP2',
'type' => 'Text',
'options' => array(
'label' => 'Nom, Prénom Responsable 2 :',
),
'attributes' => array(
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'ADRESSE_RESP2',
'type' => 'Text',
'options' => array(
'label' => 'Adresse Responsable 2 :',
'style' => 'text-transform : uppercase'
),
'attributes' => array(
'class' => 'form-control'
)
));
$this->add(array(
'name' => 'TEL_RESP2',
'type' => 'Text',
'options' => array(
'label' => 'Téléphone Responsable 2 :',
),
'attributes' => array(
'pattern' => '^0[1-78]([-. ]?[0-9]{2}){4}$',
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'MAIL_RESP2',
//'type' => 'Zend\Form\Element\Email',
'type' => 'Text',
'options' => array(
'label' => 'Mail Responsable 2 :',
),
'attributes' => array(
'class' => 'form-control',
)
));
$this->add(array(
'name' => 'AUTORISE1',
'type' => 'Text',
'options' => array(
'label' => 'Nom, prénom :',
),
'attributes' => array(
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'AUTORISE2',
'type' => 'Text',
'required' => 'required',
'options' => array(
'label' => 'Nom, prénom :',
),
'attributes' => array(
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'SAITNAGER',
'type' => 'Zend\Form\Element\Checkbox',
'options' => array(
'label' => 'Sait Nager :',
'use_hidden_element' => true,
'checked_value' => 'O',
'unchecked_value' => 'N'
),
'attributes' => array(
'id' => 'input-SaitNager'
)
));
$this->add(array(
'name' => 'TRAITEMENT',
'type' => 'Zend\Form\Element\Checkbox',
'options' => array(
'label' => 'Traitement :',
'use_hidden_element' => true,
'checked_value' => 'O',
'unchecked_value' => 'N'
),
'attributes' => array(
'id' => 'input-Traitement'
)
));
$this->add(array(
'name' => 'OUITRAITEMENT',
'type' => 'Text',
'options' => array(
'label' => 'Si oui lequel :',
),
'attributes' => array(
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'ALLERGIES',
'type' => 'Zend\Form\Element\Radio',
'options' => array(
'disable_inarray_validator' => true,
'label' => '* Allergies : ',
'value_options' => array(
'Aucune' => 'Aucune',
'Asthmatiques' => 'Asthmatiques',
'Médicamenteuses' => 'Médicamenteuses',
'Alimentaires' => 'Alimentaires',
'Autres' => 'Autres',
),
),
'attributes' => array(
'id' => 'input-allegies'
)
));
$this->add(array(
'name' => 'AUTRESALLERGIES',
'type' => 'Text',
'options' => array(
'label' => 'Si autres, précisez :',
),
'attributes' => array(
'id' => 'input-autresallergies',
'class' => 'form-control',
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'AUTRESSANTE',
'type' => 'Zend\Form\Element\Textarea',
'options' => array(
'label' => 'Autres difficultés de santé :',
),
'attributes' => array(
'id' => 'input-autresante',
'class' => 'form-control',
'rows' => "5",
'style' => 'text-transform : uppercase'
)
));
$this->add(array(
'name' => 'COCHE',
'type' => 'Zend\Form\Element\Checkbox',
'options' => array(
'label' => '* Je certifie que ces informations sont correctes :',
'use_hidden_element' => true,
'checked_value' => 'O',
'unchecked_value' => ''
),
'attributes' => array(
'id' => 'checkbox-coche'
)
));
$this->add(array(
'name' => 'submit',
'type' => 'submit',
'options' => array(
'value' => 'Valider',
),
'attributes' => array(
'id' => 'validation-form-inscription',
'class' => 'button-default'
)
));
}
}
The selects concerned by my problem are named ACTIVITE1/ACTIVITE2/ACTIVITE3...
Options of these select is load with json, the idea is to propose activity depending on the birth date informed in the form.
Here is the jQuery code to load the option of the select :
$().ready(function() {
var dateNaissance = $("#input-dtNaissance").val();
if (dateNaissance != "") {
var year = $("#input-dtNaissance").val().substring(6,10);
if (year == "") {
year = 1;
}
// si date supprimée/réinitialisée
if (year == 1) {
// on supprime les activités proposées du select
$(".activites-options").remove();
} else {
$.getJSON("<?php echo $this->basePath() ?>/activite/listActivitySession1/" + year, function(data) {
data.forEach(function(element) {
var option = "<option value='" + element.ID_ACTIVITES + "' class='activites-options'>" +element.activite[0] + element.activite.substring(1).toLowerCase() + " avec " + element.INTERVENANT + " - " + element.HORAIREDEB + "/" + element.HORAIREFIN + " (" + element.site[0] + element.site.substring(1).toLowerCase() + ")" + "</option>";
$("#select-session1").append(option);
});
});
$.getJSON("<?php echo $this->basePath() ?>/activite/listActivitySession2/" + year, function(data) {
data.forEach(function(element) {
var option = "<option value='" + element.ID_ACTIVITES + "'class='activites-options'>" + element.activite[0] + element.activite.substring(1).toLowerCase() + " avec " + element.INTERVENANT + " - " + element.HORAIREDEB + "/" + element.HORAIREFIN + " (" + element.site[0] + element.site.substring(1).toLowerCase() + ")" + "</option>";
$("#select-session2").append(option);
});
});
$.getJSON("<?php echo $this->basePath() ?>/activite/listActivitySession3/" + year, function(data) {
data.forEach(function(element) {
var option = "<option value='" + element.ID_ACTIVITES + "' class='activites-options'>" + element.activite[0] + element.activite.substring(1).toLowerCase() + " avec " + element.INTERVENANT + " - " + element.HORAIREDEB + "/" + element.HORAIREFIN + " (" + element.site[0] + element.site.substring(1).toLowerCase() + ")" + "</option>";
$("#select-session3").append(option);
});
});
}
}
})
If someone got in idea, i'll appreciate it because i'm a bit stuck right now! Thanks in advance...
As I said in the comment, the problem is that your select elements don't have any options.
This means that, at validation time, the form tries to bind and validate a value that isn't in the options he knows.
In practice, the situation is the following:
Selectelement with no optionThese values exist only in the view. For the form, all these values don't exists. This means that:
activite1activity1will then result as empty, and it will be passed to the viewThis is why the values of these select areflushed when there is an error in the form.
To fix this problem, you'll have to (best solution):
ActivitySelect, where you'll create a select with all these optionsSelecttype in your form, you'll useActivitySelectA similar, simplier and a bit worse solution, would be to create a factory to the form, where you'll pass all necessary objects to create the options to your form. This will avoid to create a custom element class, but I find this solution not so clean for maintainability
Since this question has been answered a few time, I'll avoid to re-write everything in here and link one: