Reputation: 3615
I've been looking around for this, but have been having a hard time finding any examples. I have pagination added to my app but I would like to make this an Ajax/Async feature, so the full page doesn't reload. Does anyone have any examples/tutorials on best practices for this? Here is the code I already have:
Controller:
public $acronym_paginate = [
'limit' => 25,
'fields' => ['id','abbreviation', 'full_text'],
'order' => [
'Acronyms.abbreviation' => 'asc'
]
];
public function initialize() {
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent("Flash");
}
public function index() {
$this->loadModel('Acronyms');
$acronyms = $this->Acronyms->find('All')->where();
$this->set([
'acronyms' => $this->paginate($acronyms),
'_serialize' => ['acronyms']
]);
}
}
View:
<table class = "acronymTable" id = "acronymTable" name = "acronymTable" >
<thead>
<tr>
<td style="display:none;">
ID
</td>
<td width = "10%" style="border:1px solid black; font-weight: bold; padding:10px;">
Acronym
</td>
<td width = "60%" style = "border:1px solid black; font-weight: bold; padding:10px;">
Definition
</td>
</tr>
</thead>
<tbody>
<?php foreach ($acronyms as $acronym): ?>
<tr id = "<?= $acronym->id ?>" name = "<?= $acronym->id ?>">
<td style="display:none;"><?= $acronym->id ?></td>
<td style="padding-left:10px;" id="acronymName-<?= $acronym->id ?>" name="acronymName-<?= $acronym->id ?>" ><?= $acronym->abbreviation ?></td>
<td style="padding-left:10px;" id="acronymDef-<?= $acronym->id ?>" name="acronymDef-<?= $acronym->id ?>"><?= $acronym->full_text ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<td colspan="5" style="text-align: center;">
<div class="pagination pagination-large">
<ul class="pagination">
<?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>
</td>
</tr>
</tfoot>
</table>
If there are no "best practices" for this, I guess my biggest question would be how to keep the pagination buttons, but have them submit requests via jQuery Ajax call.
thanks for your help
Upvotes: 0
Views: 575
Reputation: 1855
Since the state of the Pagination
changes with every request – previous/next link may become inactive/active and numbers may be truncated/released – I’d suggest to also render the pagination in your Ajax request.
Elements
to stay DRY./src/Template/Element/Acronyms/list.ctp
<?php foreach ($acronyms as $acronym): ?>
<tr id = "<?= $acronym->id ?>" name = "<?= $acronym->id ?>">
<td style="display:none;"><?= $acronym->id ?></td>
<td style="padding-left:10px;" id="acronymName-<?= $acronym->id ?>" name="acronymName-<?= $acronym->id ?>" ><?= $acronym->abbreviation ?></td>
<td style="padding-left:10px;" id="acronymDef-<?= $acronym->id ?>" name="acronymDef-<?= $acronym->id ?>"><?= $acronym->full_text ?></td>
</tr>
<?php endforeach; ?>
/src/Template/Element/Acronyms/pagination.ctp
<div class="pagination pagination-large">
<ul class="pagination">
<?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>
Then in your view replace the appropriate code with the Elements
:
<?= $this->element('Acronyms/list', ['acronyms' => $acronyms]) ?>
<?= $this->element('Acronyms/pagination') ?>
View
for Ajax requests on your index
method./src/Template/Acronyms/ajax/index.ctp
<table id="list">
<?= $this->element('Acronyms/list', ['acronyms' => $acronyms]) ?>
</table>
<div id="pagination">
<?= $this->element('Acronyms/pagination') ?>
</div>
View
in your Controller
./src/Controller/AcronymsController.php
public function index() {
$this->loadModel('Acronyms');
$acronyms = $this->Acronyms->find('All')->where();
$this->set([
'acronyms' => $this->paginate($acronyms),
'_serialize' => ['acronyms']
]);
// render our View for Ajax requests
if ($this->request->is('ajax')) {
$this->render('ajax/index');
}
}
click
events on pagination links and replace the contents.jQuery
$(document).on('click', '.pagination a', function(e) {
e.preventDefault();
var $link = $(this);
if (!$('body').hasClass('loading')) {
$('body').addClass('loading');
$.ajax({
url: $link.attr('href')
}).done(function(html) {
var $html;
// grab Ajax response into jQuery object
$html = $(html);
// replace table body content with new <tr> elements
$('#acronymTable tbody').html($html.find('#list').html());
// replace pagination
$('#acronymTable .pagination').replaceWith($html.find('#pagination').children());
$('body').removeClass('loading');
}).fail(function() {
// if Ajax request fails fall back to just loading the target page
window.location.href = $link.attr('href');
});
}
});
Upvotes: 2