I am trying to figure out why Zend Form is not returning errors to my form.
When I take a look inside the: Zdendframework/library/form/form.php file I can see the errors are being generated:
public function isValid()
{
if ($this->hasValidated) {
return $this->isValid;
}
...
if (!$result) {
$this->setMessages($filter->getMessages());
}
return $result;
}
If I var_dump($filter->getMessages(), I see the errors.
However when I go back to my form and attempt to dump the messages, there are none available.
My Controller
$prg = $this->prg();
if ($prg instanceof Response) {
return $prg;
} elseif ($prg === false) {
return $this->getVM()->setVariables([
'form' => $this->registerForm
]);
}
$this->registerForm->setData($prg);
if ( ! $this->registerForm->isValid($prg) ) {
return new ViewModel(['form' => $this->updateForm]);
}
My form:
public function __construct(
InputFilterInterface $inputFilter,
$name = null,
$options = array()
) {
parent::__construct('register', $options);
$this->register = $inputFilter;
}
public function init()
{
$this->add(
[
'name' => 'csrfcheck',
'type' => 'csrf'
]
);
$this->add(
[
'name' => 'user',
'type' => UserFieldset::class,
'options' => [
'use_as_base_fieldset' => true
]
]
);
$this->add(
[
'name' => 'submit',
'type' => 'submit',
'attributes' => [
'value' => 'Update User',
'class' => 'btn green',
]
]
);
$this->getInputFilter()->add($this->register, 'user');
$this->setValidationGroup(
[
'csrfcheck',
'user' => [
'id',
'email',
'firstName',
'lastName',
'roles',
'state'
]
]
);
}
My FieldSet
public function __construct(
ObjectManager $objectManager,
User $userPrototype,
$name = null,
$options = array()
) {
parent::__construct($name, $options);
$this->objectManager = $objectManager;
$this->setHydrator(new DoctrineObject($objectManager));
$this->setObject($userPrototype);
}
public function init()
{
$this->add(
[
'name' => 'id',
'type' => 'hidden',
]
);
$this->add(
[
'name' => 'uuid',
'type' => 'hidden',
]
);
$this->add(
[
'name' => 'email',
'type' => 'email',
'options' => [
'label' => 'E-Mail',
'instructions' => 'Your email address',
],
'attributes' => [
'class' => 'form-control input-large'
]
]
);
$this->add(
[
'name' => 'firstName',
'type' => 'text',
'options' => [
'label' => 'Firstname',
'instructions' => 'Alphanumeric characters (A,b,c,d,e..)',
],
'attributes' => [
'class' => 'form-control',
'type' => 'text',
'pattern' => "^[a-zA-Z-]{2,128}$",
]
]
);
$this->add(
[
'name' => 'lastName',
'type' => 'text',
'options' => [
'label' => 'Last name',
'instructions' => 'Alphanumeric characters, optional ( \' )',
],
'attributes' => [
'class' => 'form-control',
'pattern' => "^[a-zA-Z'-]{2,128}$",
]
]
);
$this->add(
[
'name' => 'state',
'type' => 'select',
'options' => [
'label' => 'User State',
'value_options' => [
0 => 'Active',
1 => 'Locked',
2 => 'Deleted'
]
],
'attributes' => [
'class' => 'form-control'
]
]
);
//#TODO Multiple set to true to make this work remove attributes if this breaks other forms
$this->add(
[
'name' => 'roles',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => [
'object_manager' => $this->objectManager,
'target_class' => HierarchicalRole::class,
'property' => 'name',
'find_method' => [
'name' => 'getAccessibleRoles'
],
'label' => 'Role'
],
'attributes' => [
'multiple' => true,
]
]
);
My Filter
function __construct(
ObjectManager $objectManager,
ObjectRepository $objectRepository
) {
$this->add(
[
'name' => 'id',
'required' => true,
'filters' => [
['name' => 'Int']
]
]
);
$this->add(
[
'name' => 'uuid',
'required' => false
]
);
$this->add(
[
'name' => 'firstName',
'required' => true,
'filters' => [
['name' => 'StringTrim']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 1,
'max' => 128
]
]
]
]
);
$this->add(
[
'name' => 'lastName',
'required' => false,
'filters' => [
['name' => 'StringTrim']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 1,
'max' => 128
]
]
]
]
);
$this->add(
[
'name' => 'email',
'required' => false,
'filters' => [
['name' => 'StringTrim']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 3,
'max' => 255
]
],
[
'name' => 'EmailAddress',
'options' => [
'useDomainCheck' => true, //Set to false in order to validate local developer test mails: myemail.dev
'message' => "This is not a valid email address"
],
]
]
]
);
$this->add(
[
'name' => 'password',
'required' => false,
'filters' => [
['name' => 'StringTrim']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'max' => 128
]
]
]
]
);
$this->add(
[
'name' => 'passwordRepeat',
'required' => false,
'filters' => [
['name' => 'StringTrim']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'max' => 128
]
]
]
]
);
$this->add(
[
'name' => 'roles',
'required' => false,
'validators' => [
]
]
);
$this->add( array(
'name' => 'state',
'required' => false
));
}
And my View
<div class="portlet-body form">
<!-- BEGIN FORM-->
<div class="portlet-body form">
<?php
$form = $this->form;
$form->setAttribute('action', $this->url());
$form->setAttribute('class', 'form-horizontal form-bordered');
$form->get('user')->get('roles')->setAttribute('class','form-control input-small select2me');
$form->get('submit')->setValue('Register new user');
$form->get('submit')->setAttribute('class','btn green');
$form->prepare();
$csrf = $form->get('csrfcheck');
$user = $form->get('user');
$id = $user->get('id');
$state = $user->get('state');
$email = $user->get('email');
$firstname = $user->get('firstName');
$lastname = $user->get('lastName');
$role = $user->get('roles');
$sub = $form->get('submit');
?>
<?= $this->form()->openTag($form); ?>
<?= $this->formElement($csrf); ?>
<?= $this->formElement($id); ?>
<?= $this->formElement($state); ?>
<div class='form-body'>
<div class="form-group">
<label class="control-label col-md-3"><?= $this->formLabel($email); ?></label>
<div class="col-md-5">
<div class="input-group" style="text-align:left">
<?php echo '<div class="form-group">'.$this->formElement($email).'</div>'; ?>
</div>
<?php if (!empty($this->formElementErrors($email))) echo '<div class="alert alert-danger">'.$this->formElementErrors($email).'</div>';?>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"><?= $this->formLabel($firstname); ?></label>
<div class="col-md-5">
<div class="input-group" style="text-align:left">
<?php echo '<div class="form-group">'.$this->formElement($firstname).'</div>'; ?>
</div>
<?php echo '<div class="alert alert-danger">'.$this->formElementErrors($firstname).'</div>'; ?>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"><?= $this->formLabel($lastname); ?></label>
<div class="col-md-5">
<div class="input-group" style="text-align:left">
<?php echo '<div class="form-group">'.$this->formElement($lastname).'</div>'; ?>
</div>
<?php if (!empty($this->formElementErrors($lastname))) echo '<div class="alert alert-danger">'.$this->formElementErrors($lastname).'</div>';?>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"><?= $this->formLabel($role); ?></label>
<div class="col-md-5">
<div class="input-group" style="text-align:left">
<?php echo '<div class="form-group input-large">'.$this->formElement($role).'</div>'; ?>
</div>
<?php if (!empty($this->formElementErrors($role))) echo '<div class="alert alert-danger">'.$this->formElementErrors($role).'</div>';?>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"><?= $this->formLabel($state); ?></label>
<div class="col-md-5">
<div class="input-group" style="text-align:left">
<?php echo '<div class="form-group input-large">'.$this->formElement($state).'</div>'; ?>
</div>
<?php if (!empty($this->formElementErrors($state))) echo '<div class="alert alert-danger">'.$this->formElementErrors($state).'</div>';?>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3"></label>
<div class="col-md-5">
<div class="input-group" style="text-align:left">
<?= $this->formElement($sub); ?>
</div>
</div>
</div>
</div>
<?= $this->form()->closeTag(); ?>
EDIT
In the controller if I dump this:
$result = $this->registerForm->getInputFilter()->getMessages();
die(var_dump($result));
This outputs:
array (size=1)
'user' =>
array (size=1)
'firstName' =>
array (size=1)
'isEmpty' => string 'Value is required and can't be empty' (length=36)
As deduced from the comments and HappyCoder themselves, the problem lies in the Controller where the wrong form is being returned to the view.
if ( ! $this->registerForm->isValid($prg) ) {
return new ViewModel(['form' => $this->updateForm]);
}
Should be:
if ( ! $this->registerForm->isValid($prg) ) {
return new ViewModel(['form' => $this->registerForm]);
}
Related
I am creating page to insert data like a book. Where I'm using zend form fieldset and collection. Fieldset have only two fields heading field and content field. Heading and sub-heading have same content(fields).
Ex:
1: Heading Content
1.1: Sub Heading
Content
1.1.1: Sub Heading
Content
1.1.2: Sub Heading
Content
1.1.2.1: Sub Heading
Content
1.1.2.2: Sub Heading
Content
...
1.1.3: Sub Heading
Content
..
1.2: Sub Heading
Content
...
2: Heading Content
Note: here indexing is just to show the parent child relationship.
Code are below:
This is main form.
class BookPointlForm extends Form
{
public function __construct($name = null)
{
parent::__construct('Form');
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'points',
'attributes' => array(
'class'=> 'point_collection '
),
'options' => array(
'label' => 'Add Book Points',
'count' => 1,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type' => 'Book\Form\BookPointMainFieldset',
),
),
));
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Submit',
'id' => 'submitbutton',
'class' => 'btn btn-primary pull-right',
),
));
}
}
This fieldset is called in BookPointlForm's points collection
class BookPointMainFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct($name = null)
{
// we want to ignore the name passed
parent::__construct('Fieldset');
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'points',
'attributes' => array(
'class'=> 'point_collection '
),
'options' => array(
'label' => 'Add Book Points',
'count' => 1,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type' => 'Book\Form\BookPointFieldset',
),
),
));
$this->add(array(
'name' => 'add_nested_point',
'type' => 'Button',
'attributes' => array(
'value' => 'Add nested point',
'class'=> 'add_nested_point'
),
'options' => array(
'label' => 'Add Nested Point',
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'nested-points',
'attributes' => array(
'class'=> 'nested_point_collection '
),
'options' => array(
'label' => 'Add Book Points',
'count' => 1,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type' => 'Book\Form\BookPointFieldset',
),
),
));
}
public function exchangeArray($data) {
}
public function getInputFilterSpecification()
{
return array(
'weight' => array(
'required' => true,
),
);
}
}
This is main fieldset it contents heading and heading's content
class BookHeadingFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct($name = null)
{
$kraHeadingText = '';
// we want to ignore the name passed
parent::__construct('BookHeadingFieldset');
// $this
// ->setHydrator(new ClassMethodsHydrator(false))
// ->setObject(new KraHeading())
;
$this->add(array(
'name' => 'id',
'type' => 'Hidden',
'attributes' => array(
'value' => ''
)
));
$this->add(array(
'name' => 'manualHeadingText',
'type' => 'Textarea',
'options' => array(
'label' => 'Heading',
'label_options' => [
'disable_html_escape' => true
],
),
'labelOptions' => array(
'disable_html_escape' => true,
),
'attributes' => array(
'class' => 'form-control',
'placeholder'=>"Enter heading",
'COLS'=>"150",
// 'required' => 'true',
),
));
}
public function exchangeArray($data) {
}
public function getInputFilterSpecification()
{
return array();
}
}
...
I have a back office admin controller in which I am using the helper form in renderform() to generate a form and it is working form but I want a functionality to add a field in that form dynamically.
I have done this by helper list, while rendering the form I am returning a render list also, check renderAdditionalOptionsList() usage
public function renderForm() {
$id_citydelivery = (int) Tools::getValue('id_citydelivery');
$citydeliveryObj = new CityPortModel($id_citydelivery);
if (Validate::isLoadedObject($citydeliveryObj)) {
$_legends = $citydeliveryObj->legend;
$_legend_array = explode(',', $_legends);
foreach ($_legend_array as $_legend) {
$this->fields_value['legend_' . $_legend] = $_legend;
}
}
$temp = $this->fields_value;
$fields_form_1 = array(
'form' => array(
'legend' => array('title' => $this->l('Price and Delivery Destination Manager'), 'icon' => 'icon-cogs'),
'input' => array(
array(
'type' => 'select',
'label' => $this->l('Country'),
'name' => 'id_country',
'required' => false,
'lang' => false,
'options' => array(
'query' => $this->getCountries(),
'id' => 'value',
'name' => 'name'
)),
array(
'type' => 'text',
'label' => $this->l('Portname'),
'name' => 'portname',
'size' => 255),
array(
'type' => 'hidden',
'name' => 'id_citydelivery'
),
array(
'type' => 'text',
'label' => $this->l('Per m3'),
'name' => 'perm3',
'size' => 255),
array(
'type' => 'text',
'label' => $this->l('Service charges'),
'name' => 'servicecharges',
'size' => 255),
array(
'type' => 'text',
'label' => $this->l('Insurance'),
'name' => 'insurance',
'size' => 255),
array(
'type' => 'text',
'label' => $this->l('Inspection'),
'name' => 'inspection',
'size' => 255),
array(
'type' => 'text',
'label' => $this->l('Certificate'),
'name' => 'certificate',
'size' => 255),
array(
'type' => 'checkbox',
'label' => $this->l('Service legend'),
'name' => 'legend',
'required' => false,
'lang' => false,
'values' => array(
'query' => $this->getLegends(),
'id' => 'value',
'name' => 'name'
)),
array(
'type' => 'switch',
'label' => $this->l('Active'),
'name' => 'active',
'required' => false,
'is_bool' => true,
'values' => array(array(
'id' => 'active_on',
'value' => 1,
'label' => $this->l('Active')), array(
'id' => 'active_off',
'value' => 0,
'label' => $this->l('Inactive')))),
),
'submit' => array(
'title' => $this->l('Save'),
'type' => 'submit'
),
'buttons' => array(
array(
'href' => AdminController::$currentIndex . '&token=' . Tools::getAdminTokenLite($this->name),
'title' => $this->l('Cancle'),
'icon' => 'process-icon-cancel'
)
)
),
);
$helper = new HelperForm();
$helper->show_toolbar = false;
$helper->module = $this;
$helper->name_controller = $this->name;
$helper->toolbar_scroll = true;
$lang = new Language((int) Configuration::get('PS_LANG_DEFAULT'));
$helper->default_form_language = $lang->id;
$helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') ? Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG') : 0;
$this->fields_form = array();
$helper->identifier = $this->identifier;
$helper->submit_action = 'submitAddcitydelivery';
$helper->currentIndex = AdminController::$currentIndex;
$helper->token = Tools::getAdminTokenLite($this->name);
$helper->tpl_vars = array(
'fields_value' => $this->getFormValues($citydeliveryObj, $temp),
'languages' => $this->context->controller->getLanguages(),
'id_language' => $this->context->language->id
);
$_1 = $helper->generateForm(array($fields_form_1));
$return = $_1;
if ($this->display != 'add') {
$return .= $this->renderAdditionalOptionsList($id_citydelivery);
}
return $return;
}
public function initPageHeaderToolbar() {
if ($this->display == 'edit' || $this->display == 'add') {
$this->page_header_toolbar_btn['back_to_list'] = array(
'href' => Context::getContext()->link->getAdminLink('AdminGCardeliverycity', true),
'desc' => $this->l('Back to list', null, null, false),
'icon' => 'process-icon-back'
);
}
parent::initPageHeaderToolbar();
}
function getFormValues($citydeliveryObj, $temp) {
$arrTwo = array(
'id_citydelivery' => Tools::getValue('id_citydelivery', $citydeliveryObj->id_citydelivery),
'id_country' => Tools::getValue('id_country', $citydeliveryObj->id_country),
'portname' => Tools::getValue('portname', $citydeliveryObj->portname),
'perm3' => Tools::getValue('perm3', $citydeliveryObj->perm3),
'servicecharges' => Tools::getValue('servicecharges', $citydeliveryObj->servicecharges),
'insurance' => Tools::getValue('insurance', $citydeliveryObj->insurance),
'inspection' => Tools::getValue('inspection', $citydeliveryObj->inspection),
'certificate' => Tools::getValue('certificate', $citydeliveryObj->certificate),
'active' => Tools::getValue('active', $citydeliveryObj->active),
);
return array_merge($temp, $arrTwo);
}
protected function renderAdditionalOptionsList($id_citydelivery) {
$this->fields_list = array(
'service_name' => array(
'width' => 'auto',
'orderby' => false,
'title' => $this->l('Service Name'),
'type' => 'text',
'search' => false,
),
'service_desc' => array(
'type' => 'text',
'title' => $this->l('Service Description'),
'search' => false,
'orderby' => false,
),
'charge' => array(
'title' => $this->l('Service Charge'),
'type' => 'text',
'search' => false,
'orderby' => false,
),
'active' => array(
'title' => $this->l('Status'),
'active' => 'status',
'type' => 'bool',
'search' => false,
'orderby' => false
)
);
$linkToAdditionServiceController = Context::getContext()->link->getAdminLink('AdminAdditionalService', false);
$helperList = new HelperList();
$helperList->table = 'additional_service';
$helperList->shopLinkType = '';
$helperList->simple_header = false; //For showing add and refresh button
$helperList->identifier = 'id_additional_service';
$helperList->actions = array('edit', 'delete');
$helperList->show_toolbar = false;
$helperList->toolbar_btn['new'] = array(
'href' => $linkToAdditionServiceController . '&addadditional_service&id_citydelivery=' . $id_citydelivery . '&token=' . Tools::getAdminTokenLite('AdminAdditionalService'),
'desc' => $this->l('Add new')
);
$helperList->title = "Additional Option Manager";
$helperList->currentIndex = $linkToAdditionServiceController;
$helperList->token = Tools::getAdminTokenLite('AdminAdditionalService');
$content = $this->getListContent($id_citydelivery);
$helperList->listTotal = count($content);
return $helperList->generateList($content, $this->fields_list);
}
I'm rendering Highcharts on my page with Pjax.
My view code:
<?php Pjax::begin() ?>
<?php ActiveForm::begin() ?>
//some code there...
<?= Html::submitButton( 'Calculate', [
'class' => 'btn btn-primary',
'id' => 'calculate-button',
]);
ActiveForm::end();
?>
<?php
if ($data) {
echo $this->render('HolidayChart', ['data' => $data]);
}
?>
Highcharts widget:
echo Highcharts::widget([
'scripts' => [
'highcharts-more'
],
'htmlOptions' => ['id' => 'holidayChart-id'],
'options' => [
'chart' => [
'type' => 'columnrange',
'inverted' => true,
'zoomType' => 'y',
],
'title' => ['text' => 'Chart'],
'inverted' => true,
'yAxis' => [
'title' => [],
'type' => 'datetime',
'dateTimeLabelFormats' =>
[
'day' => '%d.%m.%Y',
],
'min' => 1514764800000,
'max' => 1546300800000
],
'xAxis' => [
'title' => ['text' => Names'],
'categories' => $data['users'],
],
'series' => [
[
'name' => 'Name',
'data' => $data['data'],
]
]
]
]);
Controller code:
$calculateForm = new CalculateHolidayForm();
$data = '';
if ($calculateForm->load(Yii::$app->request->post()) && $calculateForm->validate()) {
$data = UserHoliday::calculateHoliday(UserSubgroup::findOne($calculateForm->subgroup), $calculateForm->dateRange);
}
return $this->render('about', ['calculateForm' => $calculateForm, 'data' => $data]);
I have two questions:
1. How can I display "Loading..." message before the rendering chart?
2. How can I display "Loading..." message before update data on the chart using only the extension? (About like this https://jsfiddle.net/hLj1advd/ )
Thanks a lot!
I have the following code which creates a specific text element:
$this->add([
'type' => 'text',
'name' => 'newpassword',
'attributes' => [
'id' => 'newpassword',
'class' => 'form-control'
],
'options' => [
'label' => 'Enter New User Password',
],
]);
And I have the following code which produces my input filter definitions:
$inputFilter->add([
'name' => 'newpassword',
'required' => true,
'filters' => [
['name' => 'StringTrim'],
['name' => 'StripTags']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 6,
'max' => 256
],
]
],
]);
What I want to accomplish is adding my custom messages. Here's the way they have it in the api documentation:
$validator = new Zend\Validator\StringLength(array('min' => 8, 'max' => 12));
$validator->setMessages( array(
Zend\Validator\StringLength::TOO_SHORT =>
'The string \'%value%\' is too short',
Zend\Validator\StringLength::TOO_LONG =>
'The string \'%value%\' is too long'
));
How do I incorporate my custom validation messages into my already programmed code?
UPDATE:
I think this is where i will find success, but not sure how to do it:
$inputFilter->get('newpassword')->getValidatorChain()->
Use this-: its messageTemplates to set custom message
$inputFilter->add([
'name' => 'newpassword',
'required' => true,
'filters' => [
['name' => 'StringTrim'],
['name' => 'StripTags']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 6,
'max' => 256,
'messageTemplates'=>array(
\Zend\Validator\StringLength::TOO_SHORT =>
'The string \'%value%\' is too short',
\Zend\Validator\StringLength::TOO_LONG =>
'The string \'%value%\' is too long'
)
],
]
],
]);
I need to save the entered value of the tag, even if it is not in the list of available database.
<?php echo $form->field($model, 'tagsList')->label(false)->widget(Select2::className(), [
'data' => ArrayHelper::map(Tag::find()->all(), 'id', 'name'),
'options' => [
'multiple' => true,
'placeholder' => 'Choose tag ...',
'tags' => true
]
]); ?>
I find solution:
<?php echo $form->field($model, 'tagsList')->label(false)->widget(Select2::className(), [
'data' => ArrayHelper::map(Tag::find()->all(), 'id', 'name'),
'options' => [
'multiple' => true,
'placeholder' => 'Choose tag ...',
],
'pluginOptions' => [
'tags' => true
]
]); ?>