I have a project in CakePHP application and I want to add pagination to it. I have added pagination to it, but when I click on a page number or go to the next page my application breaks.
The page relies on variables being passed to the controller in order to display the correct data. Here is my code for the view:
<table class="table table-striped">
<thead>
<tr>
<th>Job ID</th>
<th>Date</th>
<th>Site</th>
<th> </th>
</tr>
</thead>
<tbody>
<?php foreach ($data as $jobsheet) { ?>
<tr>
<td>
<?php echo $jobsheet['Jobsheet']['jobnum']; ?>
</td>
<td>
<?php echo date("l, jS F Y", strtotime($jobsheet['Jobsheet']['jobdate'])); ?>
</td>
<td>
<span class="companyname"><strong><?php echo $jobsheet['Siteaddress']['sitename'] ?></strong></span><br />
<?php echo $jobsheet['Siteaddress']['addressline1']; ?>,
<?php echo $jobsheet['Siteaddress']['addressline2']; ?>,
<?php if ( $jobsheet['Siteaddress']['addressline3'] = '') { ?>
<?php echo $jobsheet['Siteaddress']['addressline3']; ?>,
<?php } else { ?>
<?php } ?>
<?php echo $jobsheet['Siteaddress']['city']; ?>,
<?php echo $jobsheet['Siteaddress']['county']; ?>,
<?php echo $jobsheet['Siteaddress']['country']; ?>,
<?php echo $jobsheet['Siteaddress']['postcode']; ?>
</td>
<td><a data-toggle="modal" href="#viewjobsheet<?php echo $jobsheet['Jobsheet']['id']; ?>" onClick="document.getElementById('jbif<?php echo $jobsheet['Jobsheet']['id']; ?>').src='/modal/customers/<?php echo $company['Company']['id']; ?>/jobs/<?php echo $jobsheet['Jobsheet']['id']; ?>/view/';" title="View" class="icon-eye-open"></a>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="controls">
<?php echo $this->Paginator->prev('« Previous', null, null, array('class' => 'disabled')); ?>
<?php echo $this->Paginator->numbers(); ?>
<?php echo $this->Paginator->next('Next »', null, null, array('class' => 'disabled')); ?>
<br />
<br />
<?php echo $this->Paginator->counter(array(
'format' => 'Page {:page} of {:pages}, showing {:current} records out of
{:count} total, starting on record {:start}, ending on {:end}'
));
?>
</div>
</div>
This is the controller:
function index(){
$companyid = $this->params['customer'];
$this->set('companyid', $companyid);
$siteid = $this->params['site'];
$this->loadModel('Jobsheet');
// Job Sheets
$jobsheets = $this->Jobsheet->find('all', array('conditions' => array('Jobsheet.company' => $companyid), 'recursive' => 2, 'order' => 'Jobsheet.jobdate DESC', 'limit' => '10'));
$this->set('jobsheets', $jobsheets);
$this->paginate = array(
'limit' => 10
);
$data = $this->paginate('Jobsheet');
$this->set(compact('data'));
}
While the pagination does work, it ends up loosing the variable and this breaks what I'm trying to do. What am i missing?
One method is to use PaginatorHelper::options (see the API)
For example, say we want to pass the variable $pass between Paginator page changes. So first pass the variable to the View.
public function index() {
$pass = 'testString';
$this->set(compact('pass'));
$this->set('posts', $this->paginate());
}
In the View, we can then add this to the parameters that Paginator passes when changing pages using Paginator::options and the url option.
<?php
$this->Paginator->options(array(
'url' => array(
'pass' => $pass
)
));
?>
So if you moved from page 1 to page 2, the resulting url would be something similar to:
http://localhost/cake/posts/index/pass:testString/page:2
This is also how Paginator passes sort orders and sort keys. So while "pass" in pass:testString can be anything you want, be sure not to use sort, direction, and page.
As long as you are changing pages through the Paginator links, the passed variables will remain. Note that you can access the values of the passed arguments in both the View and the Controller by the property:
$this->passedArgs
Related
Total n00b in CakePhp
Im trying to link to the view retrieved data from variable $status, defined in the controller, given the simple condition "done" or "pending".
Given the model:
<?php
class Task extends AppModel {
var $name = 'Task';
var $validate = array(
'title' => array(
'rule' => 'notEmpty',
'message' => 'Title of a task cannot be empty'
)
);
}?>
The Task Controller:
function index($status=null) {
if($status == 'done')
$tasks = $this->Task->find('all', array('conditions' => array('Task.done' => '1')));
else if($status == 'pending')
$tasks = $this->Task->find('all', array('conditions' => array('Task.done' => '0')));
else
$tasks = $this->set('Tasks', $this->Task->find('all'));
$this->set('tasks', $tasks);
$this->set('status', $status);
}
And finally The View:
<h2>Tasks</h2>
<?php if(empty($Tasks)): ?>
There are no tasks in this list
<?php else: ?>
<table>
<tr>
<th>Title</th>
<th>Status</th>
<th>Created</th>
<th>Modified</th>
<th>Actions</th>
</tr>
<?php foreach ($Tasks as $Task): ?>
<tr>
<td>
<?php echo $Task['Task']['title'] ?>
</td>
<td>
<?php
if($Task['Task']['done']) echo "Done";
else echo "Pending";
?>
</td>
<td>
<?php echo $Task['Task']['created'] ?>
</td>
<td>
<?php echo $Task['Task']['modified'] ?>
</td>
<td>
<?php echo $this->Html->link('Edit', array('action'=>'edit', $Task['Task']['id'])); ?>
<?php echo $this->Html->link('Delete', array('action'=>'delete', $Task['Task']['id']), null, 'Are you sure you want to delete this task?'); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php endif; ?>
<?php echo $this->Html->link('List Done Tasks', array('action'=>'index','done')); ?><br />
<?php echo $this->Html->link('List Pending Tasks', array('action'=>'index', 'pending')); ?><br />
Clicking the "Done Task" returns an empty list (There are no tasks in this list). Can anyone see what is wrong on the link? Thanks in advance!
You are mixing up the casing in the variable name $Tasks. In your example you are assigning the array to $tasks, but then in your view, your are trying to check a variable names $Tasks, which will turn up empty because it has never been properly set.
Change this line:
$this->set('tasks', $tasks);
To:
$this->set('Tasks', $tasks);
As mentioned by McWayWeb above to case of the variable is incorrect.
As you are setting lower case vars to use in your view i would make the change there. Change all counts of Task in the view to task.
I would also consider setting all viewVars at the same time using the below
$this->set(compact('tasks','status));
Yii Version 1.1.15
I have a model which contains a serialized array (table) in an attribut. Showing this array as a table in a view works fine.
But I want to update the table-cells and then again save the array serialized in the model. And this does not work. The output stops there (*) without errors.
Here you can see what I did:
$model->table contains a serialized array. The unserialized array looks like this:
array(
array('dog', 'cat', 'cow'),
array('meat', 'milk', 'gras'),
)
I unserialize the table in the controller:
controller: contactController.php
$model = Contact::model()->findByPk((int) $id);
$table = unserialize($model->input)
$this->render('contact_form', array(
'table' => $table));
}
And now I want to show and edit the array $table in a form as a html-table:
view: contact_form.php
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'contact-form',
));
?>
<table border="2">
<?php foreach ($table as $row): ?>
<tr>
<?php foreach ($row as $value): ?>
<td>
<!-- (*) output stops here, without errors -->
<?= $form->textArea($value, '', array('rows' => 3, 'cols' => 20)); ?>
</td>
<?php endforeach ?>
</tr>
<?php endforeach ?>
</table>
<div class="row buttons">
<?php echo CHtml::submitButton("save"); ?>
</div>
<?php $this->endWidget(); ?>
The output stops before "... textArea ...".
If I only show $table in a view (without a form) it works like a charme:
<table border="2">
<?php foreach ($table as $row): ?>
<tr>
<?php foreach ($row as $value): ?>
<td><?= CHtml::encode($value) ?></td>
<?php endforeach ?>
</tr>
<?php endforeach ?>
</table>
Hope this helps to help me :-) How can I get this nice idea working?
Actually you are missing the arguments of CactiveForm.textArea(.......)
http://www.yiiframework.com/doc/api/1.1/CActiveForm#textArea-detail
textArea($value, '', array('rows' => 3, 'cols' => 20)); ?>
Instead of it your code should be
textArea($model, $value, array('rows' => 3, 'cols' => 20)); ?>
I want to sort a table by id when clicking on it. It is working but the main thing is that the bootstrap arrow up and down icons should also be attached to the id label.
When the data is displayed in descending order, then the bootstrap arrow-bottom icon should be shown, and when the data is displayed in ascending order, then the arrow-up icon should be shown.
UsersController.php
public $paginate = array('limit'=>4);
public function index() {
$this->User->recursive = 0;
$this->set('users', $this->paginate());
}
index.ctp
<div class="users index">
<h2><?php echo __('Users'); ?></h2>
<table class="zebra-striped table-bordered " cellpadding="0" cellspacing="0">
<tr>
<th>
<a href='' >
<?php echo $this->Paginator->sort('id'); ?>
<i class='icon-arrow-up'></i>
</a>
</th>
<th><a href='' >First Name <i class='icon-arrow-down'></i>
</a> </th>
<th>Last Name <i class='icon-resize-full'></i></a></th>
</tr>
<?php foreach ($users as $user): ?>
<tr>
<td><?php echo h($user['User']['id']); ?> </td>
<td><?php echo h($user['User']['first_name']); ?> </td>
<td><?php echo h($user['User']['last_name']); ?> </td>
</tr>
<?php endforeach; ?>
</table>
<p>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
));
?> </p>
<div>
<div class="pagination">
<ul>
<?php
echo $this->Paginator->prev(__('prev'), array('tag' => 'li'),
null, array('tag' => 'li','class' => 'disabled','disabledTag' => 'a'));
echo $this->Paginator->numbers(array('separator' => '','currentTag'
=> 'a', 'currentClass' => 'active','tag' => 'li','first' => 1));
echo $this->Paginator->next(__('next'), array('tag' => 'li','currentClass' => 'disabled'), null, array('tag' => 'li','class' => 'disabled','disabledTag' => 'a'));
?>
</ul>
</div>
A Simple Solution using Jquery, just add the below 3 lines in your default application.js or in layout/default.ctp
$('th a').append(' <i class="icon-sort"></i>');
$('th a.asc i').attr('class', 'icon-sort-down');
$('th a.desc i').attr('class', 'icon-sort-up');
Another Simple CSS Based Solution, Include Font Awesome's necessary files.
th > a:after {
content: " \f0dc";
font-family: FontAwesome;
}
th > a.asc:after {
content: " \f0dd";
font-family: FontAwesome;
}
th > a.desc:after {
content: " \f0de";
font-family: FontAwesome;
}
Use PaginatorHelper::sortDir() to check the current sort direction and build the class name based on that value:
<i class='icon-arrow-<?php echo $this->Paginator->sortDir() === 'asc' ? 'up' : 'down'; ?>'></i>
To embed this into a sort link, pass the HTML as the second parameter to PaginatorHelper::sort(), and set the escape option to false:
$type = $this->Paginator->sortDir() === 'asc' ? 'up' : 'down';
$icon = "<i class='icon-arrow-" . $type . "'></i>";
echo $this->Paginator->sort('id', $icon, array('escape' => false));
That should result in a link like:
<i class='icon-arrow-up'></i>
You need also check a key, so it would be
<?php echo $this->Paginator->sort('title', 'My great title'); ?>
<?php if ($this->Paginator->sortKey() == 'title'): ?>
<i class='fa fa-sort-<?php echo $this->Paginator->sortDir() === 'asc' ? 'up' : 'down'; ?>'></i>
<?php else: ?>
<i class='fa fa-sort'></i>
<?php endif; ?>
I want to paginate in view for a custom array. My controller and view code is given below.
Controller Code:
public function admin_detail(){
$totalByDate = $this->Pbscodemetric->find('all',array('fields'=>array('created')));
$createdDate = Set::extract('/Pbscodemetric/created', $totalByDate);
$uniqueCreatedDate = array_unique($createdDate);
$finalArray = array();
foreach($uniqueCreatedDate as $created){
$downloadsArr = $this->Pbscodemetric->find('all',array('fields'=>array('downloads_iphone','downloads_ipad','downloads_android'),'conditions'=>array('created'=>$created)));
$download_iphone = array_sum(Set::extract('/Pbscodemetric/downloads_iphone',$downloadsArr));
$download_ipad = array_sum(Set::extract('/Pbscodemetric/downloads_ipad',$downloadsArr));
$downloads_android = array_sum(Set::extract('/Pbscodemetric/downloads_android',$downloadsArr));
$finalArray[$created] = array(
'downloads_iphone' => $download_iphone,
'downloads_ipad' => $download_ipad,
'downloads_android' => $downloads_android
);
}
$this->set('finalArray',$finalArray);
}
View Code:
<div class="pbscodemetrics index">
<h2><?php echo __('Pbscodemetrics List Detail'); ?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th>Date</th>
<th>iPhone</th>
<th>iPad</th>
<th>Android</th>
</tr>
<?php
foreach($finalArray as $key => $final){?>
<tr>
<td><?php echo $key;?></td>
<td><?php echo $final['downloads_iphone'];?></td>
<td><?php echo $final['downloads_ipad'];?></td>
<td><?php echo $final['downloads_android'];?></td>
</tr>
<?php }?>
</table>
</div>
<div class="actions">
<?php echo $this->element('nav');?>
</div>
Now I want to set pagination. I know in CakePHP default pagination needs Model name. But How can I do that for the above code?
Can anyone help me please..
You could implement a custom pagination, see Custom Query Pagination in the Cookbook. However, it looks like what you're doing there could be done using grouping and the SQL SUM function, that way you could then simply use the built-in pagination. Example:
$alias = $this->Pbscodemetric->alias;
$this->Pbscodemetric->virtualFields = array
(
'downloads_iphone_sum' => sprintf('SUM(`%s.downloads_iphone`)', $alias),
'downloads_ipad_sum' => sprintf('SUM(`%s.downloads_ipad`)', $alias),
'downloads_android_sum' => sprintf('SUM(`%s.downloads_android`)', $alias)
);
$this->paginate = array
(
'fields' => array
(
'downloads_iphone_sum',
'downloads_ipad_sum',
'downloads_android_sum',
'created'
),
'group' => 'created',
'order' => array
(
'created' => 'desc'
),
'limit' => 10
);
$data = $this->paginate($alias);
This will give you Paginator helper compatible results with summed downloads_iphone, downloads_ipad and downloads_android columns, grouped by the created column. It uses virtual fields in order to retreive results in the default CakePHP style, ie they will be accessible like this:
<?php foreach($results as $result): ?>
<tr>
<td><?php echo $result['Pbscodemetric']['created'];?></td>
<td><?php echo $result['Pbscodemetric']['downloads_iphone_sum'];?></td>
<td><?php echo $result['Pbscodemetric']['downloads_ipad_sum'];?></td>
<td><?php echo $result['Pbscodemetric']['downloads_android_sum'];?></td>
</tr>
<?php endforeach; ?>
hi all in my view I'm getting this error when trying to print out information in my array.
here is my function in the controller
public function view($name)
$fields = $this->Template->Field->find('list',array(
'fields'=> array('name'),
'conditions' => array(
'template_id'=> $name)));
$this->set('field', $fields);
here is the view
</br><h2>Here is your template fields</h2></br>
<?php if(!empty($field))
{
foreach($field as $name)
{?>
<tr>
<td>
<?php echo $name['Field']['name']; ?>
</tr></br>
<?php
}
}
else
{?>
<tr> <td>No Templates Found.</td></tr>
<?php
}?>
As I already answer some of your questions. So what I understood about your project is "Template hasMany Fields" and you already defined an association-ship in the corresponding models.
You should use the following code into your view:
<?php if(!empty($field))
{
foreach($field as $name)
{?>
<tr>
<td>
<?php echo $name; ?>
</td>
</tr>
<?php
}
}
else
{?>
<tr> <td>No Template Fields Found.</td></tr>
<?php
}?>
you have operation with type list so the result will be an array in [field.id] => [field.name]
then you will require following in view
<?php foreach($field as $name): ?>
<?= $name ?>
<?php endforeach ?>