I´m developing an application using Zend Framework 2 and I use FormRow helper to render a label, the input and errors (if present) in a Form.
//within the view
echo $this->formRow($form->get('Name'));
When a user submits the form without filling the required input text field FormRow render´s it with the following error message:
<label>
<span>Name: </span>
<input class="input-error" type="text" value="" placeholder="Insert Name Here" name="Name">
</label>
<ul>
<li>Value is required and can't be empty</li>
</ul>
How can I set a class for the li tag to style it afterwards?
I know that I can echo the formElementErrors with the desired class attribute via..
<?php echo $this->formElementErrors($form->get("Name"), array('class' => "valuerequired", 'message' => "errortestmessage")); ?>
..but FormRow will still render the error message without the class.
Just for reference I´m setting the entity this way:
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'Name',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
See the code of formElementErrors
Basically you could do something like:
$this->formElementErrors($elem)
->setMessageOpenFormat('<ul%s><li class="some-class">')
->setMessageSeparatorString('</li><li class="some-class">');
But that is quite unhandy...
The better solution would be to extend the Zend\Form\View\Helper\FormElementErrors by your own class and then register the view-helper formElementErrors to your class. So basically you'd have something like this:
namespace Mymodule\Form\View\Helper;
use Zend\Form\View\Helper\FormElementErrors as OriginalFormElementErrors;
class FormElementErrors extends OriginalFormElementErrors
{
protected $messageCloseString = '</li></ul>';
protected $messageOpenFormat = '<ul%s><li class="some-class">';
protected $messageSeparatorString = '</li><li class="some-class">';
}
Last thing then would be to register the view helper with this new Class. For this you provide the following code inside your Modules Module.php
public function getViewHelperConfig()
{
return array(
'invokables' => array(
'formelementerrors' => 'Mymodule\Form\View\Helper\FormElementErrors'
),
);
}
displaimer: This code isn't tested, let me know if there are some errors, but i think this should work out quite well.
Ok, the solution to my own problem was right in front of me, instead of using:
//within the view
echo $this->formRow($form->get('Name'));
I called each element of the form individually:
//within the view
echo $this->formLabel($form->get('Name'));
echo $this->formInput($form->get('Name'));
echo $this->formElementErrors($form->get("Name"), array('class' => "some_class", 'message' => "errormessage"));
Don´t know if it´s the most efficient way of doing it, plz drop a line if you think otherwise.
FormRow check if "form_element_errors" plugin registered. And if so use it as default to display error messages.
So Sam's example work. You should redefine standard plugin and inform mvc about it.
I'v done it in module.config.php
'view_helpers' => array(
'invokables' => array(
'formElementErrors'=> 'MyModule\View\Helper\FormElementErrors',
and FormRow start display errors as I wish :)
As your problem, please try
Change
//within the view
echo $this->formRow($form->get('Name'));
to
//within the view
echo $this->formRow($form->get('Name'),null,false);
// Note: add more 2 last parameters, false- for $renderErrors => will NOT render Errors Message.
//Look original function in helper/formrow.php: function __invoke(ElementInterface $element = null, $labelPosition = null, $renderErrors = null, $partial = null)
Render Errors Message as your funciton
echo $this->formElementErrors($form->get('name'), array('class' => 'your-class-here'));
From the documentation of ZF2. Here's the link: http://framework.zend.com/manual/2.0/en/modules/zend.form.view.helpers.html#formelementerrors
echo $this->formElementErrors($element, array('class' => 'help-inline'));
// <ul class="help-inline"><li>Value is required and can't be empty</li></ul>
I use echo $this->formElementErrors($form, array('class' => "error-messages")); to show all error messages in one place:
echo $this->formElementErrors($form, array('class' => "error-messages"));// Print all error messagess
echo $this->formLabel($form->get('Name'));
echo $this->formInput($form->get('Name'));
echo $this->formLabel($form->get('Name2'));
echo $this->formInput($form->get('Name2'));
Related
I would like to make navigation buttons in my view, for example index.phtml but it's not working. I did know how to do it in Zend1 but in Zend2 I have a problem. My code looks like this (file index.phtml):
$container = new \Zend\Navigation\Navigation($tableActions);
var_dump($container);
echo '<div class="table-column">';
echo $this->navigation($container)->menu();
echo '</div>';
Variable $tableAction looks like this:
public $tableActions = array(
array(
'label' => 'On/Off',
'module' => 'import',
'controller' => 'import',
'action' => 'setstatus',
'params' => array('id' => null),
),
);
I did not get any error, just whole site die on this line. var_dump returns object(Zend\Navigation\Navigation) so it's fine so far. Problem is, how to show it...
The navigation pages have dependencies which aren't being met by just creating a new container class in a view. The Mvc page needs a RouteStackInterface (Router) instance and a RouteMatch instance. Similarly Uri pages need the current Request instance.
You can see this clearly if you take a look at the Zend\Navigation\Service\AbstractNavigationFactory and its preparePages and injectComponents methods.
The view is not the right place to be instantiating menus, instead put the menu configuration spec in your module.config.php...
<?php
return array(
'navigation' => array(
'table_actions' => array(
array(
'label' => 'On/Off',
'module' => 'import',
'controller' => 'import',
'action' => 'setstatus',
'params' => array('id' => null),
),
),
),
);
Write a factory extending the AbstractNavigationFactory class and implement the getName() method which returns the name of your menu spec key (table_actions in this example)
<?php
namespace Application\Navigation\Service;
use Zend\Navigation\Service\AbstractNavigationFactory;
class TableActionsFactory extends AbstractNavigationFactory
{
/**
* #return string
*/
protected function getName()
{
return 'table_actions';
}
}
Map the factory to a service name in the service_manager spec of module.config.php ...
<?php
return array(
'navigation' => array(// as above ... )
'service_manager' => array(
'factories' => array(
'TableActionsMenu' => 'Application\Navigation\Service\TableActionsFactory',
),
),
);
Now you can call the view helper using the service name TableActionsMenu you just mapped
<div class="table-column">
<?php echo $this->navigation('TableActionsMenu')->menu(); ?>
</div>
Finally, if, as I suspect, you need to change an attribute of the page depending on the view, you can do that too, navigation containers have find* methods which can be accessed from the navigation helper and used to retrieve pages.
Here's an example looking for the page with a matching page label, then changing it before rendering (obviously not an ideal search param, but it gives you the idea)
$page = $this->navigation('TableActionsMenu')->findOneByLabel('On/Off');
$page->setLabel('Off/On');
// and then render ...
echo $this->navigation('TableActionsMenu')->menu();
I want to disable the validation on one of the zend form element based on the input on another element on the same form. I need to achieve this using javascript/jquery. Something very common but very surprisingly couldn't find it over the internet.
e.g.
In the controller:
$oFormMassEdit = new Account_Form_Returns_Return();
$this->view->form = $oFormMassEdit;
In Account_Form_Returns_Return's constructor:
$oNoteElement = new Zend_Form_Element_Textarea('option', array(
'required' => true,
));
$this->addElemet($oNoteElement)
$oReasonElement = new Zend_Form_Element_Select('note', array(
'multiOptions' => array (
'return' => 'return',
'defect' => 'Kaput',
'other' => 'Anderer Grund'
),
'required' => true,
));
$this->addElement($oReasonElement);
$this->addDisplayGroup(array('note', 'option'), 'main', array('legend' => 'Retouren'));
$this->addElement('button','send', array(
'type' => 'submit',
'label' => 'Methode speichern',
));
and finally in the view,
<?= $this->form; ?>
Javascript can't (not in a sensible way) switch Zend_Form configuration. What you can do is changing the 'required' param for certain form fields on validation. For example; If you want to allow fieldTwo to be empty if fieldOne has 'desiredValue' as value you can achieve this using the following function in your form:
public function isValid($data) {
if('desiredValue' == $data['fieldOne'])) {
$this->getElement('fieldTwo')->setRequired(false);
}
return parent::isValid($data);
}
I'm using this datamapper http://datamapper.wanwizard.eu
problem is datamapper have validation methods similar with codeigniter form validation.but not as same.
An example, a model admins model validation array:
public $validation = array(
'username' => array(
'rules' => array('unique', 'required', 'trim', 'max_length' => 60, 'min_length' => 3),
'label' => 'User'
),
'password' => array(
'rules' => array('required', 'trim', 'encrypt', 'min_length' => 6),
'label' => 'Password'
)
);
but form validation array must be like that:
public $form_validation = array(
array(
'field' => 'username',
'label' => 'User',
'rules' => 'unique|required|trim|max_length[60]|min_length[3]'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'required|trim|encrypt|min_length[6]'
)
);
I don't want to make two manual validation for new admin adding (first form validation, after datamapper validation). I think there is a way to make this with just one manual validation.
sorry my bad English, I hope you understand. Thanks in advance.
Using the Datamapper's validation alone should be enough, without the CI's form library.
When you try to save the model, the save() method will return a true or false depending on if the save was successful. If it isn't the model's error property should be filled with the error messages generated for the validation that failed. The messages can be loaded from language files with keys named appropriately, also the codeigniter's form validation library's form_validaton_lang.php is loaded too.
In your controller you could make use of them like this:
Class TheController extends CI_Controller {
function save() {
// get the model object somehow
// ...
// update attributes
$model->prop0 = $this->input->post('prop0');
$model->prop1 = $this->input->post('prop1');
// try to save it
if ($model->save()) {
// save successful
redirect(...);
} else {
// save failed load form again, with the model
$this->load->view('path/to/the/form', array('model' => $model));
}
}
}
The view could work like this:
<form method="post" action="...">
<label>prop0</label>
<input type="text" name="prop0" value="<?php print $model->prop0?> ">
<?php if (!empty($model->error->prop0)):?>
<div class="error"><?php print $model->error->prop1; ?></div>
<?php endif; ?>
<label>prop1</label>
<input type="text" name="prop1" value="<?php print $model->prop1?> ">
<?php if (!empty($model->error->prop0)):?>
<div class="error"><?php print $model->error->prop1; ?></div>
<?php endif; ?>
<buton type="submit">go</button>
</form>
The same form can be used when no previous model exists in the database, just create an empty instance of the model you need, and pass it to the form.
I'm just starting to use Zend Framework and was following the quick start documentation for the latest version (1.11.10). Everything was going just fine, but when I placed the form code and ran the application, the form did not render. My code is exactly like http://framework.zend.com/manual/en/learning.quickstart.create-form.html
On the view, I can dump the form just fine with var_dump($this->form);
I've tried echo $this->form(), echo $this->form->render(), but nothing appeared... What could it be?
This problem can occur when Zend can't find the template file for an element. Look at following code:
$element->setDecorators(array(
array('ViewScript',
array(
'viewScript' => 'directory/_input.phtml'
)
)
));
The file _input.phtml must be in the right folder for this Controller. Otherwise Zend can't find the template for input and can't successfully render your element and will not show anything.
Make sure you pass the form to the view from the controller.
In your action handler:
$this->view->form = $my_form;
In your view:
echo $this->form;
I suspected that this was the cause of your problem because Zend Framework doesn't complain if you try to echo a parameter that doesn't exist. (i.e. echo $this->some_fake_parameter won't do anything)
Ok so i tried your code, and it worked for me no problem.
Here is everything:
Controller
<?php
class IndexController extends Zend_Controller_Action
{
public function myTestAction()
{
$form = new Form_Guestbook();
// ... processing logics
if($this->getRequest()->isPost())
{
if($form->isValid($this->getRequest()->getPost()))
{
var_dump($form->getValues());
}
}
$this->view->assign('form', $form);
}
}
Form
<?php
class Form_Guestbook extends Zend_Form
{
public function init()
{
// Set the method for the display form to POST
$this->setMethod('post');
// Add an email element
$this->createElement('text', 'email', array(
'label' => 'Your email address:',
'required' => true,
'filters' => array('StringTrim'),
'validators' => array(
'EmailAddress',
)
));
// Add the comment element
$this->addElement('textarea', 'comment', array(
'label' => 'Please Comment:',
'required' => true,
'validators' => array(
array('validator' => 'StringLength', 'options' => array(0, 20))
)
));
// Add a captcha
$this->addElement('captcha', 'captcha', array(
'label' => 'Please enter the 5 letters displayed below:',
'required' => true,
'captcha' => array(
'captcha' => 'Figlet',
'wordLen' => 5,
'timeout' => 300
)
));
// Add the submit button
$this->addElement('submit', 'submit', array(
'ignore' => true,
'label' => 'Sign Guestbook',
));
// And finally add some CSRF protection
$this->addElement('hash', 'csrf', array(
'ignore' => true,
));
}
}
?>
View
<?php echo $this->form->render(); ?>
can be seen on: http://yaconiello.com/index/my-test
If this isnt working for you, you may be having a configuration error.
I had a problem like that (exact same form, since it is eclipse example)
My problem was due to misunderstanding. Since I thought that I have to directly access to the view script. I entered in the browser something like: hostname/application/view/script/something.php
But in zend all accesses should be through public folder. You have to access to the view like this: hostname/app_name/public/guestbook
hope that would help you
I have a little experience with Zend Framework, but I like to fiddle with it until it works.
But now I cannot resolve this problem.
I have a form:
<?php
class Application_Form_Login extends Zend_Form
{
protected $notEmpty;
public function init()
{
// Create NotEmpty validator
$notEmpty = new Zend_Validate_NotEmpty();
// Configure validators for username element
$notEmpty->setMessage('Gelieve dit veld in te vullen');
$this->setMethod('post');
// emailAddress
$this->addElement('text', 'emailAddress', array(
'filters' => array('StringTrim', 'StringToLower'),
'required' => true,
'validators' => array(
array('validator' => $notEmpty),
),
'label' => 'Emailadres:'
));
// password
$this->addElement('password', 'password', array(
'filters' => array('StringTrim'),
'required' => true,
'validators' => array(
array('validator' => $notEmpty),
),
'label' => 'Wachtwoord:'
));
// submit
$this->addElement('submit', 'submit', array(
'ignore' => true,
'label' => 'Inloggen'
));
}
}
A view:
<?= $this->form ?>
<?= $this->postdata ?>
And a AccountController:
<?php
class AccountController extends Zend_Controller_Action
{
public function init()
{
echo 'data:'.$this->getRequest()->getPost('emailAddress');
/* Initialize action controller here */
}
public function indexAction()
{
$this->view->postdata = var_dump($this->getRequest()->getParams());
$form = new Application_Form_Login();
$request = $this->getRequest();
if ($request->isPost()){
// THIS POINT IS NEVER REACHED
if ($form->isValid($request->getPost())){
if ($this->_isValidLogin($form->getValues())){
// Succes Redirect to the home page
$this->_helper->redirector('index', 'home');
}
else // Not succes Redirect to account page
{
$this->_helper->redirector('index', 'account');
}
}
As you see I put in a comment: // THIS POINT IS NEVER REACHED.
There are more functions in this controller, but those are not relevant for my problem.
Let explain it a bit more.
The very strange behavior is that when I put data in my fields, $this->view->postdata = var_dump($this->getRequest()->getParams() returns no POST data.
But when I put notting in the login form fields, then I see the POST data. Of course it is empty.
Like this:
array
'controller' => string 'account' (length=7)
'action' => string 'index' (length=5)
'module' => string 'default' (length=7)
'emailAddress' => string '' (length=0)
'password' => string '' (length=0)
'submit' => string 'Inloggen' (length=8)
Thus, //THIS POINT IS NEVER REACHED is actually reached when putting no data in the login form fields :-)
The question is, what are I am doing wrong? Do I deal with the Zend_Controller_Request_Http in the wrong way?
If you need more info, I should give it.
Typing down the problem gives new insights!
The problem is in my own code. On some point I redirect to the same page. A redirect means that the $_POST data is also cleared. Those data does - of course - not go with the new page request.
So if someone encounter this problem with Zend Framework, namely you get no POST or GET data on submit of your form, then you need to check your redirects.