Zend Form Element Row needs either an id or class set through Zend_Config_Ini - forms

I have the following default decorators in a Zend_Config_Ini to set up my form:
elementDecorators.viewHelper.decorator = "ViewHelper"
elementDecorators.label.decorator = "Label"
elementDecorators.errors.decorator = "Errors"
elementDecorators.htmlTag.decorator = "HtmlTag"
elementDecorators.htmlTag.options.tag = "li"
I have the following element definition also in the Zend_Config_Ini:
elements.username.type = "text"
elements.username.options.label = "Username:"
elements.username.options.required = true
and the following output is produced:
<li>
<label for="username" class="required">Username:</label>
<input type="text" name="username" id="username" value="" />
</li>
Now what I need to know is, how do I (through the ini config file preferably), set the id or class of the LI tag? I would like the following output:
<li id="form-username-element"> ... </li>
or
<li class="form-2col"> ... </li>
Update:
I was able to get it by overriding all the decorators in the element config itself like this:
elements.username.options.decorators.viewHelper.decorator = "ViewHelper"
elements.username.options.decorators.label.decorator = "Label"
elements.username.options.decorators.errors.decorator = "Errors"
elements.username.options.decorators.htmlTag.decorator = "HtmlTag"
elements.username.options.decorators.htmlTag.options.tag = "li"
elements.username.options.decorators.htmlTag.options.class = "username-row-element"
So that will work, however creates a lot of duplication as that would have to go onto every element (with the single change of the last line which would be the class setting itself). So what I am NOW wondering, is, from the ini file, is there a way to just override the class name using the default decorators (rather than having to duplicate all of the decorators for each element)?

Easiest thing to do is create your own Decorator. For instance, I've created an ElementWrap decorator, which wraps each element with a div and adds the necessary class and id. It could look something like this:
class Form_Decorator_ElementWrap extends Zend_Form_Decorator_Abstract
{
public function render($content)
{
$element = $this->getElement();
if($this->getOption('openOnly')) {
return '<div class="'.$this->getClass().'" id="'.$this->getId().'">' . $content;
} else if($this->getOption('closeOnly')) {
return $content . PHP_EOL . '</div>' . PHP_EOL;
} else {
return '<div class="'.$this->getClass().'" id="'.$this->getId().'">' . $content . '</div>';
}
}
public function getClass()
{
$element = $this->getElement();
$classes = array(
'field_wrap',
'field_' . strtolower(substr(strrchr($element->getType(), '_'), 1)),
$this->getOption('class'),
);
if($element->hasErrors()) {
$classes[] = 'field_error';
}
if($elementClass = $element->getAttrib('class')) {
$classes[] = $elementClass;
}
return implode(' ', array_filter($classes));
}
public function getId()
{
return 'fieldwrap-' . $element->getId();
}
}

Related

Zend : Error Occurs when create html file from zend phtml file for multiple employee

//controller function
function sendBulkMailAction(){
$template = "estimated-festival-bill-single.phtml";
foreach ($employeeArr as $profile_id => $employeeValue) {
$someData = array(); //here include some salary data
$model = new ViewModel($someData);
$model->setTemplate($template);
$htmlContent = "<!DOCTYPE html>\n\r<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\r<head>
<meta charset=\"utf-8\">
</head>
<body>"
. $this->getServiceLocator()->get('viewrenderer')->render($model)
. "</body>
</html>";
//create html file
//create pdf link from html by wkhtmlToPdf
//send this link via email to employee
}
}
//estimated-festival-bill-single.phtml
//simple code
<div> Employee Name</div>
<br>
<div><?php echo _get_salary_html(); ?></div>
<?php
function _get_salary_html(){
return "Salary Data";
}
?>
error show
Fatal error: Cannot redeclare _get_salary_html() (previously declared in G:\xampp\htdocs\ums\module\Hrm\view\hrm\salary-reports\estimated-salary-bill-single.phtml:9) in G:\xampp\htdocs\ums\module\Hrm\view\hrm\salary-reports\estimated-salary-bill-single.phtml on line 10
hints: when single employee its ok but for multiple employee show error
Because you are re-declaring function unknowingly. Add a condition around the function like below.
if (!function_exists('_get_salary_html')) {
function _get_salary_html() {
........
}
}

How to filter New WP Query by Custom Field Value?

I am creating new pages for each of my categories in wordpress. The post editor has a custom field that allows the selection of a sector type, this gets applied to the post on update. The custom field key is: sector, for custom field meta value options lets use SectorA, SectorB and SectorC. I am using a custom post type called projects.
I followed the advice at this link http://weblogtoolscollection.com/archives/2008/04/13/how-to-only-retrieve-posts-with-custom-fields/
How can I change the query line in the code below so that it filters the loop by a Sector name, lets use SectorA. I'll then reuse the code on each template page changing the value to SectorB and SectorC on the other pages.
I think this needs changing somehow:
$customPosts->query('showposts=5&sector=sectorA&post_type=projects' );
Currently it echos the sector value and description value successfully but is showing all the posts. So my attempt to limit it to sectorA using sector=sectorA doesn't seem to work?
This code is in functions.php:
function get_custom_field_posts_join($join) {
global $wpdb, $customFields;
return $join . " JOIN $wpdb->postmeta postmeta ON (postmeta.post_id = $wpdb->posts.ID and postmeta.meta_key in ($customFields)) ";
}
function get_custom_field_posts_group($group) {
global $wpdb;
$group .= " $wpdb->posts.ID ";
return $group;
}
And this code is on the Template Page:
<?php /* Begin Custom Field Posts */ ?>
<h2>Custom Posts</h2>
<ul>
<?php
global $customFields;
$customFields = "'sector', 'description'";
$customPosts = new WP_Query();
add_filter('posts_join', 'get_custom_field_posts_join');
add_filter('posts_groupby', 'get_custom_field_posts_group');
$customPosts->query('showposts=5&sector=sectorA&post_type=projects' );//Uses same parameters as query_posts
remove_filter('posts_join', 'get_custom_field_posts_join');
remove_filter('posts_groupby', 'get_custom_field_posts_group');
while ($customPosts->have_posts()) : $customPosts->the_post();
$sector = get_post_custom_values("sector");
$description= get_post_custom_values("description");?>
<li><?php echo $sector[0]; ?></li>
<li><?php echo $description[0]; ?></li><br />
<?php endwhile; ?>
</ul>
<?php /* End Custom Field Posts */ ?>
Thanks for your help
May be this what you want
function get_custom_field_posts_join($join) {
global $wpdb, $customSector;
return $join . " JOIN $wpdb->postmeta postmeta ON (postmeta.post_id = $wpdb->posts.ID and postmeta.meta_key = 'sector' and postmeta.value = '$customSector') ";
}
and modification of page
$customSector='sectorA';//<--- insert this
add_filter('posts_join', 'get_custom_field_posts_join');
Try using this code.
<?php
$sector = get_post_meta($post->ID, "sector", false);
if ($sector[0]=="") { ?>
<!-- If there are no custom fields, show nothing -->
<?php } else { ?>
<div class="sector">
<h3>Title</h3>
<?php foreach($sector as $sector) {
echo '<blockquote><p>'.$sector.'</p></blockquote>';
} ?>
</div>
<?php } ?>

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.

Strange behaviour with Zend_Element 'belongsTo' property

I've seen other threads and bug reports to do with the belongsTo property of an Zend_Element but nothing that relates directly to what i'm experiencing..
Here is my (simplified) Zend_Form:
$form = new Zend_Form();
$form->addElement('text', 'fname', array('belongsTo' => 'user'));
$form->addElement('text', 'sname', array('belongsTo' => 'user'));
Which is fine and the elements render like so:
<input type="text" name="user[fname]" />
<input type="text" name="user[sname]" />
...which is exactly what i want.
However, when the form is submitted, the element values are only accessible if you call
$form->getValue('fname') or $form->getValue('sname')
NOT, if you call...
$form->getValue('user');
What i'm expecting to see when you call $form->getValues('user') is an array of the values.
The array of values is clearly visible if you call
$form->getValues();
If this is the expected behaviour, then whats the point of putting them in an array? Because there would be no distinction between "user[fname]" and "client[fname]" - in fact adding another element with name "fname", even though it belongs to another item, would overwrite the previous.
I've tried adding a sub form which does result in what i want, but that way all the sub-form elements get rendered together, what i really want is to lay the 'array' elements in random places, like this...
<input type="text" name="user[fname]" />
<input type="text" name="some-other-field" />
<input type="text" name="some-other-field2" />
<input type="text" name="user[sname]" />
<input type="text" name="another-field-too" />
$form->getValue('fname') or $form->getValue('sname')
works this way because getValue() is just looking for the name of the element, and the names of your elemnts are fname and sname.
Excerpt: Zend/Form.php
public function getValue($name)
{
if ($element = $this->getElement($name)) {
return $element->getValue();
}
the way to access your belongsTo data from what I've seen should be:
$data = $form->getValues();
$user=$data['user'];
this should do what you want. Based on this:
Excerpt: Zend/Form.php
public function getValues($suppressArrayNotation = false)
{
$values = array();
$eBelongTo = null;
if ($this->isArray()) {
$eBelongTo = $this->getElementsBelongTo();
}
foreach ($this->getElements() as $key => $element) {
if (!$element->getIgnore()) {
$merge = array();
if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) {
if ('' !== (string)$belongsTo) {
$key = $belongsTo . '[' . $key . ']';
}
}
$merge = $this->_attachToArray($element->getValue(), $key);
$values = $this->_array_replace_recursive($values, $merge);
}
}
//...Code continues
return $values;
Hope this helps.

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.