Zend_Paginator: no page number on links on a page with no page number specified by the URL - zend-framework

Without sticking /1 onto a url is there away to change Zend_Paginator to approach a URL? Currently the user goes to /aaron/studio. Then the user should click through the paging and start accessing URLS such as : /aaron/studio/2
I have this rule:
$router->addRoute('studios/page', new Zend_Controller_Router_Route(':id/studio/:page',array('module' => 'default', 'controller' => 'studio', 'action' => 'view')));
If I go-to /aaron/studio/2, the Paginator links correctly to other pages, if i goto /aaron/studio it doesn't link to other pages, just the page its on.
What I need todo somehow it make Paginator aware that of its location even without a page in the URL.
Heres my controller code if it helps:
$page = $this->_getParam('page', 1);
$from = ($page * $this->clips_per_page) - $this->clips_per_page;
$count = Model_Clip::load_by_type(array('type' => 'studio_id', 'values' => $object->id, 'to' => 0, 'to' => COUNT_HIGH, 'count' => 1, 'order' => 'd.views DESC'));
$paginator = Zend_Paginator::factory($count);
$paginator->setItemCountPerPage($this->clips_per_page);
$paginator->setCurrentPageNumber($page);
$paginator->setPageRange(25);
$this->view->paginator = $paginator;
Edit, heres my view as requested:
<?php if (count($this->paginator) && $this->paginator->count() > 1): ?>
<?php echo $this->paginationControl($this->paginator, 'Sliding', 'pagination.phtml', array('translate' => $this->translate)); ?>
<?php endif; ?>
and the partial
<div class="pagination-control" style="width: auto; text-align: center; margin: 0 auto">
<div style="width: auto;">
<!-- First page link -->
<?php if (isset($this->previous)): ?>
Start |
<?php else: ?>
<!-- <span class="disabled">Start |</span> -->
<?php endif; ?>
<!-- Previous page link -->
<?php if (isset($this->previous)): ?>
Previous |
<?php else: ?>
<!-- <span class="disabled"> Previous |</span> -->
<?php endif; ?>
<!-- Numbered page links -->
<?php foreach ($this->pagesInRange as $page): ?>
<?php if ($page != $this->current): ?>
<?php echo $page; ?>
<?php else: ?>
<span class="chosen"><?php echo $page; ?></span>
<?php endif; ?>
<?php endforeach; ?>
<!-- Next page link -->
<?php if (isset($this->next)): ?>
| Next |
<?php else: ?>
<!-- <span class="disabled">| Next |</span> -->
<?php endif; ?>
<!-- Last page link -->
<?php if (isset($this->next)): ?>
End
<?php else: ?>
<!-- <span class="disabled">End</span> -->
<?php endif; ?>
<p>
Page <?php echo $this->current; ?> of <?php echo $this->last; ?>
</p>
</div>
<p class="clear"></p>
</div>

I had the same problem, and I just figured out that the problem was in the route.
First I had specified the route like this:
$router->addRoute(
'projects',
new Zend_Controller_Router_Route('/:lang/projects/:category/',
array('lang' => 'en',
'module' => 'index',
'controller' =>'projects',
'action' =>'index'
)
)
);
so the paginator was not printing the page numbers when generating the links, when I changed the route and put the :page var the paginator worked. The final route is:
$router->addRoute(
'projects',
new Zend_Controller_Router_Route('/:lang/projects/:category/:page',
array('lang' => 'en',
'module' => 'index',
'controller' =>'projects',
'action' =>'index',
'page' => 1
)
)
);

Try providing a default value of 1 for :page in the router
http://framework.zend.com/manual/en/zend.controller.router.html#zend.controller.router.routes.standard
(scroll down to Variable Defaults)
$router->addRoute('studios/page',
new Zend_Controller_Router_Route(':id/studio/:page',
array('module' => 'default', 'controller' => 'studio', 'action' => 'view'),
array('page' => 1)));

Related

How do i loop to display post category title?

Please, pardon me for unending questions. I am just a newbie as far as wordpress theme development is concerned. I am just cracking my brain to get something done. I have successfully worked on my code and it gives one category title. The category title of the post is not appropriate. I beg someone out there to help look into my code below and help me correct where necessary. I am just tired over this issue.
I want it to display appropriate category title above the post as you can see about. The category title is outside the loop and not within. It is equally not in category page rather at the front page.
`<?php
$args = array(
'post_type' => 'product',
'posts_per_page' => 6,
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'building',
)
)
);
$q = new WP_Query( $args );
$leadingcount = 3;
$cats = get_terms( array( 'taxonomy' => 'product_cat' ) );
// loop through the categries
foreach ($cats as $cat) {
// setup the cateogory ID
$cat_id= $cat->term_id;
// Make a header for the cateogry
echo "<h6 class='mt-5 text-center'>".$cat->name."</h6>"; ?>
<?php if (have_posts()) : while ( $q->have_posts() ) : $q->the_post(); ?>
<article class="item col-lg-<?php echo $leadingcount; ?>">
<div class="card rounded-0">
<div class="card-body">
<a href="<?php the_permalink(); ?>">
<h5><?php the_title(); ?></h5>
</a>
<?php the_excerpt(); ?>
<?php the_category(); ?>
</div>
</div>
</article>
<?php endwhile; endif; // done our wordpress loop. Will start again for each category ?>
<?php } // done the foreach statement ?>
`

ZF2 Elements "select" and "multicheckbox" not render correctly

Why elements "select" and "multicheckbox" not render correctly (in html)?
Element "text" and "checkbox" render correctly!
Example:
1) Code in form:
class Profile extends Form {
public function __construct($name = null) {
parent::__construct('page');
$this->setAttribute('action', 'info');
$this->setAttribute('method', 'post');
$this->setInputFilter($this->getFilters());`
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'usernames',
'attributes' => array(
'id' => 'usernames'
),
'options' => array(
'label' => 'User Name',
'options' => array(
'test' => 'Hi, Im a test!',
'Foo' => 'Bar',
),
),
));
$this->add(array(
'type' => 'select',
'name' => 'language',
'options' => array(
'label' => 'Which is your mother tongue?',
'value' => array(
'0' => 'French',
'1' => 'English',
'2' => 'Japanese',
'3' => 'Chinese',
),
)
));
}
2) Code in view:
<h1><?php echo $this->translate('Profile') ?></h1>
<?php $form = $this->form; $form->prepare();?>
<?php echo $this->form()->openTag($form) ?>
<dl class="zend_form">
<?php foreach ($form as $element): ?>
<?php if ($element->getLabel() != null): ?>
<dt><?php echo $this->translate($this->formLabel($element)); ?></dt>
<?php endif ?>
<?php if ($element instanceof Zend\Form\Element\Button): ?>
<dd><?php echo $this->formButton($element) ?></dd>
<?php elseif ($element instanceof Zend\Form\Element\Captcha): ?>
<dd><?php echo $this->formCaptcha($element) . $this->translate($this->formElementErrors($element)); ?></dd>
<?php else: ?>
<dd><?php echo $this->formInput($element) . $this->translate($this->formElementErrors($element)); ?></dd>
<?php endif ?>
<?php endforeach ?>
</dl>
<?php if ($this->redirect): ?>
<input type="hidden" name="redirect" value="<?php echo $this->redirect ?>" />
<?php endif ?>
<input type="submit" value="<?php echo $this->translate('Submit'); ?>" />
<?php echo $this->form()->closeTag() ?>
3) Code in html, after render:
...
<dt><label for="usernames">User Name</label></dt>
<dd><input type="select" name="usernames" id="usernames" value=""></dd>
<dt><label for="language">Which is your mother tongue?</label></dt>
<dd><input type="select" name="language" value=""></dd>
...
it is not correctly!?
...
<select>
<option>value 1</option>
<option>value 2</option>
</select>
... - that's correct)
The formInput() helper is specifically for outputting <input> elements, so ZF is doing exactly what you've told it to. You probably want something more like this:
<?php foreach ($form as $element): ?>
<?php if ($element->getLabel() != null): ?>
<dt><?php echo $this->translate($this->formLabel($element)); ?></dt>
<?php endif ?>
<dd><?php echo $this->formElement($element) . $this->translate($this->formElementErrors($element)) ?></dd>
<?php endforeach ?>
The formElement() helper will call whatever helper is appropriate.

Yii bootstrap submit a form inside a modal window using the modal buttons

I'm trying to submit a form from inside a modal window using the modal buttons in the modal-footer.
The form itself is loaded through ajax from a link (controller/action).
Just to be clearer I attached this picture:
This is the code for the modal:
<?php $this->beginWidget('bootstrap.widgets.TbModal', array('id'=>'modal')); ?>
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h4>Client Ticket Status Update</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<?php $this->widget('bootstrap.widgets.TbButton', array(
'buttonType'=>'ajaxSubmit',
'type'=>'primary',
'label'=>'Save changes',
'url'=>'#',
'htmlOptions'=>array('data-dismiss'=>'modal'),
)); ?>
<?php $this->widget('bootstrap.widgets.TbButton', array(
'label'=>'Close',
'url'=>'#',
'htmlOptions'=>array('data-dismiss'=>'modal'),
)); ?>
</div>
<?php $this->endWidget(); ?>
This is the javascript that loads the form inside the modal:
$("a[data-toggle=modal]").click(function(){
var target = $(this).attr('data-target');
var url = $(this).attr('href');
if(url){
$(target).find(".modal-body").load(url);
}
});
This is the form view:
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'client-ticket-form',
'enableAjaxValidation'=>false,
)); ?>
<p class="note">Fields with <span class="required">*</span> are required. </p>
<?php echo $form->errorSummary($ticket); ?>
<div>
<?php echo $form->labelEx($ticket,'sent_to'); ?>
<?php echo $form->textField($ticket,'sent_to'); ?>
<?php echo $form->error($ticket,'sent_to'); ?>
</div>
<div>
<?php echo $form->labelEx($ticket,'courier'); ?>
<?php echo $form->textField($ticket,'courier'); ?>
<?php echo $form->error($ticket,'courier'); ?>
</div>
<div>
<?php echo $form->labelEx($ticket,'awb'); ?>
<?php echo $form->textField($ticket,'awb'); ?>
<?php echo $form->error($ticket,'awb'); ?>
</div>
<div>
<?php echo $form->labelEx($ticket,'awb_date'); ?>
<?php echo $form->textField($ticket,'awb_date'); ?>
<?php echo $form->error($ticket,'awb_date'); ?>
</div>
<div class="buttons">
<?php echo CHtml::submitButton($ticket->isNewRecord ? 'Create' : 'Save'); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
Any help is very appreciated. If you require more information, please ask.
Change code at model-footer as below:
<div class="modal-footer">
<?php $this->widget('bootstrap.widgets.TbButton', array(
'type'=>'primary',
'label'=>'Save changes',
'url'=>'#',
'htmlOptions'=>array('onclick' => '$("#formID").submit()'),
)); ?>
<?php $this->widget('bootstrap.widgets.TbButton', array(
'label'=>'Close',
'url'=>'#',
'htmlOptions'=>array('data-dismiss'=>'modal'),
)); ?>
This first response didn't resolve my problem of a modal form closing on submit. For anyone else that is having issues, I had to enable client Validation in the CActiveForm.
It ended up looking like this:
$form = $this->beginWidget(
'CActiveForm',
array(
'id' => 'feature-form',
'enableAjaxValidation' => true,
'enableClientValidation' => true,
'clientOptions' => array(
'validateOnSubmit' => true,
'validateOnChange' => true,
'validateOnType' => true
)
)
);
Hopefully this helps some coming after me.
just trigger the click event on the other one that you don't want to show, an also hide it first!

zend framework components DB can't find class Zend_Paginator_Adapter_DbTableSelect

I'm using some Zend libraries outside of the Zend Framework in a small project.
I'm using Zend_Db and Zend_Paginator but when I'm trying to set up the pagination using Zend_Paginator_Adapter_DbTableSelect I get an error that it can't find the class.
Fatal error: Class 'Zend_Paginator_Adapter_DbTableSelect' not found in C:\xampp\htdocs\php_testing\zend\zend_db\index1.php on line 65
Here is my code:
<?
require_once 'Zend/Db.php';
$config=array(
'adapter' => 'PDO_MYSQL',
'hostname' => 'localhost',
'dbname' => 'dm_xxxx',
'username' => 'un',
'password' => 'pw'
);
$db=Zend_Db::factory($config['adapter'], $config);
$select=$db->select()
->from('photocontest__photos', array('*'))
->order('created')
;
require_once 'Zend/Paginator.php';
$currentPageNumber = ($_GET['page'] > 0)?$_GET['page']:'1';
$totalNumberOfItems = 11;
$itemsPerPage = 5;
$pageRange = 10;
$adapter = new Zend_Paginator_Adapter_DbTableSelect($select);
$paginator = new Zend_Paginator($adapter);
$paginator->setCurrentPageNumber($currentPageNumber);
$paginator->setItemCountPerPage($itemsPerPage);
$scrollType = 'Sliding';
$paginator = get_object_vars($paginator->getPages($scrollType));
foreach($paginator AS $item){
echo $item->title.'<br>';
}
?>
thanks
######### UPDATE EDIT ##########
<?
$config=array(
'adapter' => 'PDO_MYSQL',
'hostname' => 'localhost',
'dbname' => 'dm_xxxx',
'username' => 'un',
'password' => 'pw'
);
require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();
$db=Zend_Db::factory($config['adapter'], $config);
$table = new Photos(array('db' => $db));
$select = $table->select();
$select->setIntegrityCheck(false)
->from('photocontest__photos', array('*'))
->order('created')
;
$currentPageNumber = ($_GET['page'] > 0)?$_GET['page']:'1';
$itemsPerPage = 6;
$adapter = new Zend_Paginator_Adapter_DbTableSelect($select); //Setup the adapter object
$paginator = new Zend_Paginator($adapter); //Setup the actual paginator object
$paginator->setCurrentPageNumber($currentPageNumber);
$paginator->setItemCountPerPage($itemsPerPage); // items pre page
$scrollType = 'Sliding'; //change this to 'All', 'Elastic', 'Sliding' or 'Jumping' to test all scrolling types
Zend_Paginator::setDefaultScrollingStyle('Sliding'); // Sliding or Elastic
//Zend_View_Helper_PaginationControl::setDefaultViewPartial('pagination.phtml');
$paginatorControl = get_object_vars($paginator->getPages($scrollType)); //and that's it! we can now use the $paginator variable as we want
?>
<h1>Zend_Paginator Demo</h1>
<ul id="items">
<?php foreach($paginator AS $item): ?>
<li><?php echo $item->title; ?></li>
<?php endforeach ?>
</ul>
<div id="paginator">
<p>Showing <strong><?php echo $paginatorControl['firstItemNumber'] ?> to <?php echo $paginatorControl['lastItemNumber'] ?></strong> out of <strong><?php echo $paginatorControl['totalItemCount'] ?></strong> items</p>
<?php if($paginatorControl['previous']): ?>
« Prev
<?php else: ?>
<span>« Prev</span>
<?php endif ?>
<?php if($paginatorControl['firstPageInRange'] > $paginatorControl['first']): ?>
<?php echo $paginatorControl['first'] ?>
<span>...</span>
<?php endif ?>
<?php foreach($paginatorControl['pagesInRange'] as $page): ?>
<?php if($page == $paginatorControl['current']): ?>
<span><?php echo $page ?></span>
<?php else: ?>
<?php echo $page ?>
<?php endif ?>
<?php endforeach ?>
<?php if($paginatorControl['lastPageInRange'] < $paginatorControl['last']): ?>
<span>...</span>
<?php echo $paginatorControl['last'] ?>
<?php endif ?>
<?php if($paginatorControl['next']): ?>
Next »
<?php else: ?>
<span>Next »</span>
<?php endif ?>
</div>
Edited: I dont think my frirst solution will help you unless you can live without Zend_Paginator_Adapter_DbTableSelect. But looking at your code have you tried including directely DbTableSelect.php?
Try using ::factory.
$paginator = Zend_Paginator::factory($adapter);
$paginator->setCurrentPageNumber($currentPageNumber);
$paginator->setItemCountPerPage($itemsPerPage);
$scrollType = 'Sliding';
$paginator = get_object_vars($paginator->getPages($scrollType));
<?
$config=array(
'adapter' => 'PDO_MYSQL',
'hostname' => 'localhost',
'dbname' => 'dm_xxxx',
'username' => 'un',
'password' => 'pw'
);
require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();
$db=Zend_Db::factory($config['adapter'], $config);
$table = new Photos(array('db' => $db));
$select = $table->select();
$select->setIntegrityCheck(false)
->from('photocontest__photos', array('*'))
->order('created')
;
$currentPageNumber = ($_GET['page'] > 0)?$_GET['page']:'1';
$itemsPerPage = 6;
$adapter = new Zend_Paginator_Adapter_DbTableSelect($select); //Setup the adapter object
$paginator = new Zend_Paginator($adapter); //Setup the actual paginator object
$paginator->setCurrentPageNumber($currentPageNumber);
$paginator->setItemCountPerPage($itemsPerPage); // items pre page
$scrollType = 'Sliding'; //change this to 'All', 'Elastic', 'Sliding' or 'Jumping' to test all scrolling types
Zend_Paginator::setDefaultScrollingStyle('Sliding'); // Sliding or Elastic
//Zend_View_Helper_PaginationControl::setDefaultViewPartial('pagination.phtml');
$paginatorControl = get_object_vars($paginator->getPages($scrollType)); //and that's it! we can now use the $paginator variable as we want
?>
<h1>Zend_Paginator Demo</h1>
<ul id="items">
<?php foreach($paginator AS $item): ?>
<li><?php echo $item->title; ?></li>
<?php endforeach ?>
</ul>
<div id="paginator">
<p>Showing <strong><?php echo $paginatorControl['firstItemNumber'] ?> to <?php echo $paginatorControl['lastItemNumber'] ?></strong> out of <strong><?php echo $paginatorControl['totalItemCount'] ?></strong> items</p>
<?php if($paginatorControl['previous']): ?>
« Prev
<?php else: ?>
<span>« Prev</span>
<?php endif ?>
<?php if($paginatorControl['firstPageInRange'] > $paginatorControl['first']): ?>
<?php echo $paginatorControl['first'] ?>
<span>...</span>
<?php endif ?>
<?php foreach($paginatorControl['pagesInRange'] as $page): ?>
<?php if($page == $paginatorControl['current']): ?>
<span><?php echo $page ?></span>
<?php else: ?>
<?php echo $page ?>
<?php endif ?>
<?php endforeach ?>
<?php if($paginatorControl['lastPageInRange'] < $paginatorControl['last']): ?>
<span>...</span>
<?php echo $paginatorControl['last'] ?>
<?php endif ?>
<?php if($paginatorControl['next']): ?>
Next »
<?php else: ?>
<span>Next »</span>
<?php endif ?>
</div>

How do I use ViewScripts on Zend_Form File Elements?

I am using this ViewScript for my standard form elements:
<div class="field" id="field_<?php echo $this->element->getId(); ?>">
<?php if (0 < strlen($this->element->getLabel())) : ?>
<?php echo $this->formLabel($this->element->getName(), $this->element->getLabel());?>
<?php endif; ?>
<span class="value"><?php echo $this->{$this->element->helper}(
$this->element->getName(),
$this->element->getValue(),
$this->element->getAttribs()
) ?></span>
<?php if (0 < $this->element->getMessages()->length) : ?>
<?php echo $this->formErrors($this->element->getMessages()); ?>
<?php endif; ?>
<?php if (0 < strlen($this->element->getDescription())) : ?>
<span class="hint"><?php echo $this->element->getDescription(); ?></span>
<?php endif; ?>
</div>
Trying to use that ViewScript alone results in an error:
Exception caught by form: No file
decorator found... unable to render
file element
Looking at this FAQ revealed part of my problem, and I updated my form element decorators like this:
'decorators' => array(
array('File'),
array('ViewScript', array('viewScript' => 'form/field.phtml'))
)
Now it's rendering the file element twice, once within my view script, and extra elements with the file element outside my view script:
<input type="hidden" name="MAX_FILE_SIZE" value="8388608" id="MAX_FILE_SIZE" />
<input type="hidden" name="UPLOAD_IDENTIFIER" value="4b5f7335a55ee" id="progress_key" />
<input type="file" name="upload_file" id="upload_file" />
<div class="field" id="field_upload_file">
<label for="upload_file">Upload File</label>
<span class="value"><input type="file" name="upload_file" id="upload_file" /></span>
</div>
Any ideas on how to handle this properly with a ViewScript?
UPDATE: Based on Shaun's solution, here's my final code:
Form Element:
$this->addElement('file', 'upload_file', array(
'disableLoadDefaultDecorators' => true,
'decorators' => array('File', array('ViewScript', array(
'viewScript' => '_form/file.phtml',
'placement' => false,
))),
'label' => 'Upload',
'required' => false,
'filters' => array(),
'validators' => array(array('Count', false, 1),),
));
View Script:
<?php
$class .= 'field ' . strtolower(end(explode('_',$this->element->getType())));
if ($this->element->isRequired()) {
$class .= ' required';
}
if ($this->element->hasErrors()) {
$class .= ' errors';
}
?>
<div class="<?php echo $class; ?>" id="field_<?php echo $this->element->getId(); ?>">
<?php if (0 < strlen($this->element->getLabel())): ?>
<?php echo $this->formLabel($this->element->getFullyQualifiedName(), $this->element->getLabel());?>
<?php endif; ?>
<span class="value"><?php echo $this->content; ?></span>
<?php if ($this->element->hasErrors()): ?>
<?php echo $this->formErrors($this->element->getMessages()); ?>
<?php endif; ?>
<?php if (0 < strlen($this->element->getDescription())): ?>
<p class="hint"><?php echo $this->element->getDescription(); ?></p>
<?php endif; ?>
</div>
The answer is relatively simple as it happens. All you need do is specify the File decorator first, create a specific view script for the file input and specify false for the placement in the viewScript decorator arguments, this will effectively inject the output from the File decorator into the viewScript decorator e.g.
$element->setDecorators(array('File', array('ViewScript', array('viewScript' => 'decorators/file.phtml', 'placement' => false))));
Then in the new file element view script you simply echo $this->content in the script where you'd like the file input markup to be placed. Here's an example from a recent project, so ignore the markup if it looks a little odd, hopefully it will illustrate the point.
<label for="<?php echo $this->element->getName(); ?>" class="element <?php if ($this->element->hasErrors()): ?> error<?php endif; ?>" id="label_<?php echo $this->element->getName(); ?>">
<span><?php echo $this->element->getLabel(); ?></span>
<?php echo $this->content; ?>
<?php if ($this->element->hasErrors()): ?>
<span class="error">
<?php echo $this->formErrors($this->element->getMessages()); ?>
</span>
<?php endif; ?>
</label>
When rendered you will see this html for the element
<label for="photo" class="element" id="label_photo">
<span>Photo</span>
<input type="hidden" name="MAX_FILE_SIZE" value="6291456" id="MAX_FILE_SIZE">
<input type="file" name="photo" id="photo">
</label>
This is not a simple or ideal solution because it requires an extension of the File decorator... but it's rather frustrating that they didn't make the effort to separate the hidden element generation logic from the file input generation logic. I'm not sure if the file view helper handles the issue of an element being an array (that seems to be the reason they did it this way.)
Extension of File Decorator:
(the commented out part is what causes the extra input to be generated.)
<?php
class Sys_Form_Decorator_File extends Zend_Form_Decorator_File {
public function render($content) {
$element = $this->getElement();
if (!$element instanceof Zend_Form_Element) {return $content;}
$view = $element->getView();
if (!$view instanceof Zend_View_Interface) {return $content;}
$name = $element->getName();
$attribs = $this->getAttribs();
if (!array_key_exists('id', $attribs)) {$attribs['id'] = $name;}
$separator = $this->getSeparator();
$placement = $this->getPlacement();
$markup = array();
$size = $element->getMaxFileSize();
if ($size > 0) {
$element->setMaxFileSize(0);
$markup[] = $view->formHidden('MAX_FILE_SIZE', $size);
}
if (Zend_File_Transfer_Adapter_Http::isApcAvailable()) {
$apcAttribs = array('id' => 'progress_key');
$markup[] = $view->formHidden('APC_UPLOAD_PROGRESS', uniqid(), $apcAttribs);
}
else if (Zend_File_Transfer_Adapter_Http::isUploadProgressAvailable()) {
$uploadIdAttribs = array('id' => 'progress_key');
$markup[] = $view->formHidden('UPLOAD_IDENTIFIER', uniqid(), $uploadIdAttribs);
}
/*
if ($element->isArray()) {
$name .= "[]";
$count = $element->getMultiFile();
for ($i = 0; $i < $count; ++$i) {
$htmlAttribs = $attribs;
$htmlAttribs['id'] .= '-' . $i;
$markup[] = $view->formFile($name, $htmlAttribs);
}
}
else {$markup[] = $view->formFile($name, $attribs);}
*/
$markup = implode($separator, $markup);
switch ($placement) {
case self::PREPEND: return $markup . $separator . $content;
case self::APPEND:
default: return $content . $separator . $markup;
}
}
}
?>
Form setup in controller action:
$form = new Zend_Form();
$form->addElement(new Zend_Form_Element_File('file'));
$form->file->setLabel('File');
$form->file->setDescription('Description goes here.');
$decorators = array();
$decorators[] = array('File' => new Sys_Form_Decorator_File());
$decorators[] = array('ViewScript', array('viewScript' => '_formElementFile.phtml'));
$form->file->setDecorators($decorators);
$this->view->form = $form;
In action view:
<?php echo $this->form; ?>
In element script:
<div class="field" id="field_<?php echo $this->element->getId(); ?>">
<?php if (0 < strlen($this->element->getLabel())) : ?>
<?php echo $this->formLabel($this->element->getName(), $this->element->getLabel());?>
<?php endif; ?>
<span class="value">
<?php
echo $this->{$this->element->helper}(
$this->element->getName(),
$this->element->getValue(),
$this->element->getAttribs()
);
?>
</span>
<?php if (0 < $this->element->getMessages()->length) : ?>
<?php echo $this->formErrors($this->element->getMessages()); ?>
<?php endif; ?>
<?php if (0 < strlen($this->element->getDescription())) : ?>
<span class="hint"><?php echo $this->element->getDescription(); ?></span>
<?php endif; ?>
</div>
Output should be:
<form enctype="multipart/form-data" action="" method="post">
<dl class="zend_form">
<input type="hidden" name="MAX_FILE_SIZE" value="134217728" id="MAX_FILE_SIZE" />
<div class="field" id="field_file">
<label for="file">File</label>
<span class="value"><input type="file" name="file" id="file" /></span>
<span class="hint">Description goes here.</span>
</div>
</dl>
</form>
A problem with this solution is that the hidden elements don't render within the viewscript; this might be a problem if you're using the div as a selector in a client-side script...
What I've realized is, a custom decorator class will handle most fields except File fields.
Make sure your class implements the interface like so:
class CC_Form_Decorator_Pattern
extends Zend_Form_Decorator_Abstract
implements Zend_Form_Decorator_Marker_File_Interface
This worked for me.
This helped me fix my problem. I adjusted the code to wrap the file element inside a table. To make it work, simply remove the label from the viewdecorator and add the file element as follows:
$form->addElement('file', 'upload_file', array(
'disableLoadDefaultDecorators' => true,
'decorators' => array(
'Label',
array(array('labelTd' => 'HtmlTag'), array('tag' => 'td', 'class' => 'labelElement')),
array(array('elemTdOpen' => 'HtmlTag'), array('tag' => 'td', 'class' => 'dataElement','openOnly' => true, 'placement' => 'append')),
'File',
array('ViewScript', array(
'viewScript' => 'decorators/file.phtml',
'placement' => false,
)),
array(array('elemTdClose' => 'HtmlTag'), array('tag' => 'td', 'closeOnly' => true, 'placement' => 'append')),
array(array('row' => 'HtmlTag'), array('tag' => 'tr'))
),
'label' => 'Upload',
'required' => false,
'filters' => array(),
'validators' => array(array('Count', false, 1), ),
));
I've found a work-around that avoids the ViewScript altogether.
First, the element definition:
$this->addElement('file', 'upload_file', array(
'disableLoadDefaultDecorators' => true,
'decorators' => array(
'File',
array(array('Value'=>'HtmlTag'), array('tag'=>'span','class'=>'value')),
'Errors',
'Description',
'Label',
array(array('Field'=>'HtmlTag'), array('tag'=>'div','class'=>'field file')),
),
'label' => 'Upload File',
'required' => false,
'filters' => array('StringTrim'),
'validators' => array(),
));
Second, after the form class has been instantiated, I mimic the behavior of my ViewScript:
$field = $form->getElement('upload_file');
$decorator = $field->getDecorator('Field');
$options = $decorator->getOptions();
$options['id'] = 'field_' . $field->getId();
if ($field->hasErrors()) {
$options['class'] .= ' errors';
}
$decorator->setOptions($options);
I guess that I should look into class-based decorators. Maybe there's more flexibility there?
The easiest thing to do is to add no markup at all to the output in your custom File Decorator:
class Custom_Form_Decorator_File extends Zend_Form_Decorator_File {
public function render($content) {
return $content;
}
}
now you can do whatever you want in your viewscript for this file element (output the file input field and all hidden fields you need on your own).
Just in case you have followed #Shaun's answer and you are still getting the error: make sure that you've disabled default decorators for the element in question (take look at line 2):
$this->addElement('file', 'upload_file', array(
'disableLoadDefaultDecorators' => true,
'decorators' => array('File', array('ViewScript', array(
'viewScript' => '_form/file.phtml',
'placement' => false,
))),
'label' => 'Upload',
'required' => false,
'filters' => array(),
'validators' => array(array('Count', false, 1),),
));