Zend framework 2 - standalone forms - forms

Is it possible to use the ZF2 forms a as standalone component? This was possible with ZF1, but I can't figure it out with ZF2.
I can create a form and a validator, but can't figure out how to render the form:
$form = new AddressBookForm('address_book'); \\ extends Zend\Form\Form
if ($this->input->isPost()) {
$validator = new AddressBookValidator(); \\ implements Zend\InputFilter\InputFilterAwareInterface
$form->setInputFilter($validator->getInputFilter());
$form->setData($this->input->getPost());
if ($form->isValid()) {
echo 'valid'; exit;
}
}
// Render form somehow here???
I tried creating a view, but couldn't figure out how to give it the view helpers. Thanks.

I have a basic solution, that seems to do the job
$zfView = new \Zend\View\Renderer\PhpRenderer();
$plugins = $zfView->getHelperPluginManager();
$config = new Zend\Form\View\HelperConfig;
$config->configureServiceManager($plugins);
and then render the form
echo $zfView->form()->openTag($form);
echo $zfView->formRow($form->get('name'));
echo $zfView->formSubmit( $form->get('submit'));
echo $zfView->form()->closeTag();

Checkout this blog.
Form Render in View file
you can do simply by zend framework form view helper.
$form = $this->form;
$form->prepare();
$this->form()->render($form);

#CodeMonkey's method is a good one but the code is incomplete. I cobbled together a working example from his and other answers I found with partial code.
<?php
/*
* #author Carl McDade
*
* #since 2012-06-11
* #version 0.2
*
*/
namespace zftest;
$path = DOCROOT .'/_frameworks/zf/ZendFramework-2.2.2/library';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
require_once($path . '/Zend/Loader/StandardAutoloader.php');
use Zend\Loader;
use Zend\Http\Request;
use Zend\Http\Client;
use Zend\Captcha;
use Zend\Form\Element;
use Zend\Form\Fieldset;
use Zend\Form\Form;
use Zend\Form\FormInterface;
use Zend\InputFilter\Input;
use Zend\InputFilter\InputFilter;
use Zend\Form\View\Helper;
use \Common;
class zftest{
function __construct()
{
spl_autoload_register(array($this, '_zftest_autoload'));
}
function _zftest_autoload($class)
{
//
$loader = new \Zend\Loader\StandardAutoloader(array('autoregister_zf' => true));
$loader->registerNamespaces(array('Zend'));
// finally send namespaces and prefixes to the autoloader SPL
$loader->register();
return;
}
function zftest()
{
$uri = 'http://maps.google.com/maps/api/geocode/json';
$address = urlencode('berlin');
$sensor = 'false';
$request = new Request();
$request->setUri($uri);
$request->setMethod('GET');
$client = new Client($uri);
$client->setRequest($request);
$client->setParameterGet(array('sensor'=>$sensor,'address'=>$address));
$response = $client->dispatch($request);
if ($response->isSuccess()) {
print 'Your Request for:<pre>' . print_r($address, 1) . '</pre>';
print '<pre>' . print_r($response->getBody(), 1) . '</pre>';
}
}
function zfform()
{
// Zend Framework 2 form example
$name = new Element('name');
$name->setLabel('Your name');
$name->setAttributes(array(
'type' => 'text'
));
$email = new Element\Email('email');
$email->setLabel('Your email address');
$subject = new Element('subject');
$subject->setLabel('Subject');
$subject->setAttributes(array(
'type' => 'text'
));
$message = new Element\Textarea('message');
$message->setLabel('Message');
$captcha = new Element\Captcha('captcha');
$captcha->setCaptcha(new Captcha\Dumb());
$captcha->setLabel('Please verify you are human');
$csrf = new Element\Csrf('security');
$send = new Element('send');
$send->setValue('Submit');
$send->setAttributes(array(
'type' => 'submit'
));
$form = new Form('contact');
$form->add($name);
$form->add($email);
$form->add($subject);
$form->add($message);
$form->add($captcha);
$form->add($csrf);
$form->add($send);
$nameInput = new Input('name');
// configure input... and all others
$inputFilter = new InputFilter();
// attach all inputs
$form->setInputFilter($inputFilter);
$zfView = new \Zend\View\Renderer\PhpRenderer();
$plugins = $zfView->getHelperPluginManager();
$config = new \Zend\Form\View\HelperConfig;
$config->configureServiceManager($plugins);
$output = $zfView->form()->openTag($form) . "\n";
$output .= $zfView->formRow($form->get('name')) . "<br />\n";
$output .= $zfView->formRow($form->get('captcha')) . "<br />\n";
$output .= $zfView->formSubmit( $form->get('send')) . "<br />\n";
$output .= $zfView->form()->closeTag() . "\n";
echo $output;
}
}
?>

You can use the Zend\Form\View\Helper view helpers to render the form inside a view.
Example: (view context)
My Form:
<?php echo $this->form()->openTag($this->form); ?>
<?php echo $this->formCollection($this->form); ?>
<?php echo $this->form()->closeTag($this->form); ?>
Note that $this->form is the $form variable assigned to the view. Also, view helpers are always available in views as far as they are registered as invokables (this is always true for built-in helpers).
This would render all elements inside a <form ...> ... </form> tag.
Check the other view helpers for further information.
Also, see the example docs: http://zf2.readthedocs.org/en/latest/modules/zend.form.quick-start.html
There's a lot more you can do with this.

None of the simpler answers helped me since I did not have Service Manager set up nor the View Helper methods.
But in a hurry this worked for me:
$checkbox = new Element\Checkbox('checkbox');
$checkbox->setLabel('Label');
$checkbox->setCheckedValue("good");
$checkbox->setUncheckedValue("bad");
$form = new FormCheckbox();
echo $form->render($checkbox);

Related

Joomla module not working

I made a module that display how many days ago a article was published
it looks like this.
{source}
<?php
$jinput = JFactory::getDocument()->input;
$option = $jinput->get('option');
$view = $jinput->get('view');
if ($option=="com_content" && $view=="article") {
$ids = explode(':',JRequest::getString('id'));
$article_id = $ids[0];
$article =& $jinput->get("content");
$article->load($article_id);
$date = new JDate($article->get("publish_up"));
$currentTime = new JDate('now');
$interval = $date->diff($currentTime);
if($interval->d == 0) {
echo 'dzisiaj' . "<br>";
}
else if( $interval->d == 1) {
echo 'wczoraj' . "<br>";
}
else if( $interval->d > 1) {
echo $interval->format('%a dni temu') . "<br>";
}
}
?>
{/source}
And it works on my local joomla but when use it on custom template it doesnt work. I'm using Joomla 3.4.8.
The issue is you're trying to access the input values using Document Factory that's wrong you have to use
$jinput = JFactory::getApplication()->input;
Document Factory is used for other purpose like adding , styles or Js to the pages etc. read more about input here.
Hope it make sense.

Zend Framework 2 form element error-class + custom ViewHelper to render form

This is my third question this week (and overall) - hope I don't get banned here :D
Anyway, searched around and couldn't find an exact explanation to solve my issue(s).
A. I've searched around and found a custom ViewHelper to render my forms. What it does is recursively get all fieldsets and when it gets to the element level, it goes like this:
public function renderElement($element) {
$html = '
<div class="row">' .
'<label class="col-md-12" for="' . $element->getAttribute('id') . '">' . $element->getLabel() . '</label>' .
$this->view->formElement($element) .
$this->view->FormElementErrors($element) .
'<div class="clearfix" style="height: 15px;"></div>';
return $html . PHP_EOL;
}
Form renders ok, except:
1) How can I add an error class to the form element? (like if I use formRow helper in my view, it automatically ads an 'input-error' class, while also keeping the initial class specified in my fieldset when creating the element - 'attributes' => array('class' => 'some-class')), so the element's class attribute becomes "some-class input-error" in case it's invalid.
2) How can I set a class for the 'ul' containing the error messages (the 'ul' rendered by $this->view->FormElementErrors($element))? Hope this is a one-liner and I don't have to go message-by-message and compose the html for the error messages list, but if not so be it (I don't know how to do that either).
B. Let's say that sometimes I don't use this custom ViewHelper to render my form. Zend's formRow view helper can be handy sometimes. This brings me to the following code in my view:
echo $this->formRow($this->form->get('user_fieldset')->get('user_name'));
I've noticed this automatically adds 'input-error' class on my element (in case it's invalid) which is perfect, BUT how can I also tell formRow to give a class to the 'ul' that's displaying the error messages?
I'd go even further and ask how I can turn this:
echo $this->formLabel($this->form->get('user_fieldset')->get('user_name'));
echo $this->formInput($this->form->get('user_fieldset')->get('user_name'));
echo $this->formElementErrors($this->form->get('user_fieldset')->get('user_name'), array('class' => 'form-validation-error'));
into something that ads an error-class to the element as well, not just to the error messages list, but if anyone answers to point A I think it's the same issue.
I've managed to do it like this:
public function renderElement($element) {
// FORM ROW
$html = '<div class="form-group">';
// LABEL
$html .= '<label class="form-label" for="' . $element->getAttribute('id') . '">' . $element->getLabel() . '</label>';
// ELEMENT
/*
- Check if element has error messages
- If it does, add my error-class to the element's existing one(s),
to style the element differently on error
*/
if (count($element->getMessages()) > 0) {
$classAttribute = ($element->hasAttribute('class') ? $element->getAttribute('class') . ' ' : '');
$classAttribute .= 'input-error';
/*
* Normally, here I would have added a space in my string (' input-error')
* Logically, I would figure that if the element already has a class "cls"
* and I would do $element->getAttribute('class') . 'another-class'
* then the class attribute would become "clsanother-class"
* BUT it seems that, even if I don't intentionally add a space in my string,
* I still get "cls another-class" as the resulted concatenated string
* I assume that when building the form, ZF2 automatically
* adds spaces after attributes values? so you/it won't have to
* consider that later, when you'd eventually need to add another
* value to an attribute?
*/
$element->setAttribute('class', $classAttribute);
}
$html .= $this->view->formElement($element);
/*
* Of course, you could decide/need to do things differently,
* depending on the element's type
switch ($element->getAttribute('type')) {
case 'text':
case 'email': {
break;
}
default: {
}
}
*/
// ERROR MESSAGES
// Custom class (.form-validation-error) for the default html wrapper - <ul>
$html .= $this->view->FormElementErrors($element, array('class' => 'form-validation-error'));
$html .= '</div>'; # /.form-group
$html .= '<div class="clearfix" style="height: 15px;"></div>';
return $html . PHP_EOL;
}
I'm not to fond of this, but I suppose there is no shorter way. I thought ZF2 shoud have something like:
if ($element->hasErrors()) { $element->addClass('some-class'); }
right out of the box. That's the answer I would have expected, that it would simply be a method I missed/couldn't find. But it turns out that ZF2 doesn't have quite anything in the whole world that you might need right out of the box, you end up having to write the (more or less) occasional helpers.
Anyway, if someone ever needs it here's the entire RenderForm view helper:
namespace User\View\Helper;
use Zend\View\Helper\AbstractHelper;
class RenderForm extends AbstractHelper {
public function __invoke($form) {
$form->prepare();
$html = $this->view->form()->openTag($form) . PHP_EOL;
$html .= $this->renderFieldsets($form->getFieldsets());
$html .= $this->renderElements($form->getElements());
$html .= $this->view->form()->closeTag($form) . PHP_EOL;
return $html;
}
public function renderFieldsets($fieldsets) {
foreach ($fieldsets as $fieldset) {
if (count($fieldset->getFieldsets()) > 0) {
$html = $this->renderFieldsets($fieldset->getFieldsets());
} else {
$html = '<fieldset>';
// You can use fieldset's name for the legend (if that's not inappropriate)
$html .= '<legend>' . ucfirst($fieldset->getName()) . '</legend>';
// or it's label (if you had set one)
// $html .= '<legend>' . ucfirst($fieldset->getLabel()) . '</legend>';
$html .= $this->renderElements($fieldset->getElements());
$html .= '</fieldset>';
// I actually never use the <fieldset> html tag.
// Feel free to use anything you like, if you do have to
// make grouping certain elements stand out to the user
}
}
return $html;
}
public function renderElements($elements) {
$html = '';
foreach ($elements as $element) {
$html .= $this->renderElement($element);
}
return $html;
}
public function renderElement($element) {
// FORM ROW
$html = '<div class="form-group">';
// LABEL
$html .= '<label class="form-label" for="' . $element->getAttribute('id') . '">' . $element->getLabel() . '</label>'; # add translation here
// ELEMENT
/*
- Check if element has error messages
- If it does, add my error-class to the element's existing one(s),
to style the element differently on error
*/
if (count($element->getMessages()) > 0) {
$classAttribute = ($element->hasAttribute('class') ? $element->getAttribute('class') . ' ' : '');
$classAttribute .= 'input-error';
$element->setAttribute('class', $classAttribute);
}
$html .= $this->view->formElement($element);
// ERROR MESSAGES
$html .= $this->view->FormElementErrors($element, array('class' => 'form-validation-error'));
$html .= '</div>'; # /.row
$html .= '<div class="clearfix" style="height: 15px;"></div>';
return $html . PHP_EOL;
}
}
User is my module. I've created a 'viewhelper.config.php' in it's config folder:
return array(
'invokables' => array(
'renderForm' => 'User\View\Helper\RenderForm',
),
);
and in Module.php:
public function getViewHelperConfig() {
return include __DIR__ . '/config/viewhelper.config.php';
}
Then, in your view simply call:
$this->renderForm($form);
Of course, if you don't have many view helpers, you could not create a separate config file just for that, leave Module.php alone and simply add:
'view_helpers' => array(
'invokables' => array(
'renderForm' => 'User\View\Helper\RenderForm',
),
),
to any configuration file.
I use getMessages() method to check if an element has an validation message. for eg.
<div class="form-group <?=($this->form->get('user_fieldset')->get('user_name')->getMessages())?'has-error':'';?>">
...
</div>
This question seems to be very old and you must have solved it by yourself. :)

Zend - How do I combine a form and pagination in the same view

This is probably simpler that it seems but I am stumped. I have a simple controller that builds a small form for inputting parameters. When the form is submitted, the same page is redrawn with the same form at the top but with a paginated view of results under it. My controller is here:
public function indexAction()
{
$form = new Application_Form_Battery();
$request = $this->getRequest();
if ($request->isPost()) {
$data = $request->getPost();
$form->populate($data);
// get the data
Zend_View_Helper_PaginationControl::setDefaultViewPartial('pagination.phtml');
$reportsTBL = new Model_DBTable_Reports();
$paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($reportsTBL->getBatteryLog($data)));
$paginator->setCurrentPageNumber($this->_getParam('page',1))
->setItemCountPerPage(50);
$this->view->paginator = $paginator;
}
$this->view->form = $form;
}
As you can see, after the form is submitted, the paginated results are overwritten by the view->form statement... How can I combine them after form submit? I can't have two view calls...
Some thing like untested here,
indexController
public function indexAction()
{
.....
$_category = new Admin_Model_DbTable_Category();
$category = $_category->browse($browseArray);
$this->view->vCount = count($category);
$paginator = Zend_Paginator::factory($category);
$page = ($postData['page'] > 0) ? $postData['page'] : 1;
$paginator->setCurrentPageNumber($page);
$paginator->setItemCountPerPage(10);
$paginator->setPageRange(5);
$this->view->categoryList = $paginator; // print_obj($paginator);
....
}
index.phtml
.....
<ul>
<?php if (count($this->categoryList) != 0) { ?>
<?php
foreach ($this->categoryList AS $key => $category) {
?>
<li>
<div >
<?php echo $category['name'] ?>
</div>
</li>
<?php } ?>
<li>
<div><?php echo "Total Category(" . $this->vCount . ")"; ?></div>
<div style="text-align:center;"><?php echo $this->paginationControl($this->categoryList, 'Sliding', 'pagination.phtml'); ?></div>
</li>
<?php } else { ?>
<li><div style="text-align:center;">No records found</div></li>
<?php } ?>
</ul>
...
Category.php
class Admin_Model_DbTable_Category extends Zend_Db_Table_Abstract
{
...
protected $_name = 'category';
protected $_primary = 'category_id';
public function browse($browseArray = array())
{
extract($browseArray);
$whereSQL = ' `parent` = 0 ';
if($category_id)
$whereSQL .= ' AND `category_id` = "'. $category_id .'"';
if($catname)
$whereSQL .= ' AND `name` = "'. $catname .'"';
if($name)
$whereSQL .= ' AND `name` LIKE "%'. $name .'%"';
if($description)
$whereSQL .= ' AND `description` LIKE "%'. $description .'%"';
if($status)
$whereSQL .= ' AND `status` = "'. $status .'"';
$select = $this->_db->select()
->from($this->_name)
->where($whereSQL);
$result = $this->getAdapter()->fetchAll($select);
return $result;
}
....
}
You can use general function named browse which will fetch result from table , by using the result we can paginate the data when page is rendering.
I solved it. I was using a view that called a form template and I was trying to display the paginated results on that form. I moved the paginated results to the actual view script and everything is solved.
Thanks for the help.

Zend_Form_Element_MultiCheckbox: How to display a long list of checkboxes as columns?

So I am using a Zend_Form_Element_MultiCheckbox to display a long list of checkboxes. If I simply echo the element, I get lots of checkboxes separated by <br /> tags. I would like to figure out a way to utilize the simplicity of the Zend_Form_Element_MultiCheckbox but also display as multiple columns (i.e. 10 checkboxes in a <div style="float:left">). I can do it manually if I had an array of single checkbox elements, but it isn't the cleanest solution:
<?php
if (count($checkboxes) > 5) {
$columns = array_chunk($checkboxes, count($checkboxes) / 2); //two columns
} else {
$columns = array($checkboxes);
}
?>
<div id="checkboxes">
<?php foreach ($columns as $columnOfCheckboxes): ?>
<div style="float:left;">
<?php foreach($columnOfCheckboxes as $checkbox): ?>
<?php echo $checkbox ?> <?php echo $checkbox->getLabel() ?><br />
<?php endforeach; ?>
</div>
<?php endforeach; ?>
</div>
How can I do this same sort of thing and still use the Zend_Form_Element_MultiCheckbox?
The best place to do this is using a view helper. Here is something I thought of really quickly that you could do. You can use this in your view scripts are attach it to a Zend_Form_Element.
I am going to assume you know how to use custom view helpers and how to add them to form elements.
class My_View_Helper_FormMultiCheckbox extends Zend_View_Helper_FormMultiCheckbox
{
public function formMultiCheckbox($name, $value = null, $attribs = null,
$options = null, $listsep = "<br />\n")
{
// zend_form_element attrib has higher precedence
if (isset($attribs['listsep'])) {
$listsep = $attribs['listsep'];
}
// Store original separator for later if changed
$origSep = $listsep;
// Don't allow whitespace as a seperator
$listsep = trim($listsep);
// Force a separator if empty
if (empty($listsep)) {
$listsep = $attribs['listsep'] = "<br />\n";
}
$string = $this->formRadio($name, $value, $attribs, $options, $listsep);
$checkboxes = explode($listsep, $string);
$html = '';
// Your code
if (count($checkboxes) > 5) {
$columns = array_chunk($checkboxes, count($checkboxes) / 2); //two columns
} else {
$columns = array($checkboxes);
}
foreach ($columns as $columnOfCheckboxes) {
$html .= '<div style="float:left;">';
$html .= implode($origSep, $columnOfCheckboxes);
$html .= '</div>';
}
return $html;
}
}
If you need further explanation just let me know. I did this fairly quickly.
EDIT
The reason I named it the same and placed in a different directory was only to override Zend's view helper. By naming it the same and adding my helper path:
$view->addHelperPath('My/View/Helper', 'My_View_Helper');
My custom view helper gets precedence over Zend's helper. Doing this allowed me to test without changing any of my forms,elements, or views that used Zend's helper. Basically, that's how you replace one of Zend's view helpers with one of your own.
Only reason I mentioned the note on adding custom view helpers and adding to form elements was because I assumed you might rename the helper to better suit your needs.

how to email form on submit using zend_form?

OK. I finally got my zend form working, validating, filtering and sending the contents to my process page (by using $form->populate($formData);)
Now, how do I email myself the contents of a form when submitted? Is this a part of Zend_form or some other area I need to be looking in?
Thanks!
You can use Zend Mail for this, Zend form does not offer such functions.. but its an nice idea.
In your controleller, after $form->isValid();
if ($form->isValid($_POST)) {
$mail = new Zend_Mail();
$values = $form->getValues();
$mailText = 'My form valueS: ';
foreach ($values as $v) {
$mailText .= 'Value ' . $v . PHP_EOL;
}
$mail->setFrom('user#user.de', 'user');
$mail->AddTo('Me#me.de', 'me');
$mail->setSubject->$form->getName();
$mail->send();
} else {
// what ever
}