I'm using a custom pagination template with CakePHP 3.7
The template is in config/infinite-scroll-paginator.php. I want to use this with the Infinite Scroll jquery plugin. Therefore all that's required is 1 link per paginated page which contains the URL to the "next" page (i.e. next set of results).
So in the file above I have:
$config = [
'nextActive' => '<a class="pagination__next" aria-label="Next" href="{{url}}">{{text}}</a>'
];
In my Controller I start by telling it to use the custom pagination template:
public $helpers = [
'Paginator' => ['templates' => 'infinite-scroll-paginator']
];
Then when I want to paginate my data I use a custom finder (findFilters() which is in Model/Table/FiltersTable.php):
public $paginate = [
'finder' => 'filters',
];
I can then use this to get paginated data:
$this->loadModel('Filters');
$rf_keywords = trim($this->request->getQuery('rf_keywords'));
// Pagination
$page = $this->request->getQuery('page') ? (int)$this->request->getQuery('page') : 1;
$this->paginate = ['page' => $page, 'limit' => 100];
$finder = $this
->Filters
->find('filters', [
'rf_keywords' => $rf_keywords
]);
$data = $this->paginate($finder);
$this->set('data', $data);
Then in my template I output the paginator HTML:
<?= $this->Paginator->next(); ?>
All of this works fine. I get a "next" link for each page. Say if I have 10 pages I get URL's:
/get-filters/?page=1
/get-filters/?page=2
...
/get-filters/?page=10
The issue is that on the 10th page there is a "next" link and the URL of it is just
/get-filters
There are no more pages to output but I still get a link, albeit an invalid one.
How can I stop it from outputting the link on the last page? I thought that the paginator component would take care of this since it's aware how many pages there are based on my limit value in $this->paginate?
Use $this->Paginator->hasNext() which returns true or false depending on whether there is a "next page".
In the template:
<?php if ($this->Paginator->hasNext()): ?>
<?= $this->Paginator->next(); ?>
<?php endif; ?>
Related
I have a controller that has two paginations which is reflected in my view but anytime I want to click on page 2, the controller doesnt know which page it is clicking on and I get an error.
class AsController extends AppController
{
public function view ($id = null)
{
$data1 = $this->paginate('Post','Post.foriegn_id' => $id);
$data1 = $this->paginate('Author','Author,foreign_id' => $id);
// rest of the code goes here
}
}
I have two sections in my view page
<div class="post view"> and div class="author view"
And in each of tehse sections I have the following code:
<div class="paging">
<?php
echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));
echo $this->Paginator->numbers(array('separator' => ''));
echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled'));
?>
</div>
Please assist me in any way to rectify this issue
Cheers
It looks like its more of a structure/design issue. You are using the same id to get posts and authors. Do you have a relationship between posts and authors you can just paginate through one of the models? From what I know the pagination built into cake is meant to work with one model per request. Especially due to how the pagination helper uses the url params. Do you have a case where you want to show page 1 of posts and page 2 of authors? Also in your view action you have your second paginate() saving to the same $data1 var which is overwriting the previous. Not sure if this is a typo.
I would suggest only using one main section of pagination per page. If the data of the authors relates to the posts I would suggest containing and displaying it in the same paginated section.
I am making blog and url route is like this-
Router::connect('/blog/c/:catid/*',
array('controller' => 'blogarticles', 'action' => 'index'));
it works well with url as- /blog/c/3/other-articles
but when i use paginator in view as
echo $this->Paginator->numbers();
it generates url as- /blogarticles/index/other-articles/page:2
What changes should in make in paginator to generate proper url.
Please suggest possible solution , Thanks in advance
This should solve your problem:
$this->Paginator->options(
array(
'controller' => 'blog',
'action' => 'c',
$catid,
$title
)
);
The trick is to pass blog as the controller and c as the action, and all other variables (NOT LIMITED TO $catid and $title) as additional parameters, sequentially!
NOTE: I assumed here that you have "set" $catid and $title from your Controller, to the current "category id" and "title" respecting. I also assumed that your URLs are always in the format: /blog/c/:catid/:title
You may also want to view my answer to a similar question: https://stackoverflow.com/a/25097693/2862423
What you want is to set the options for the PaginatorHelper for that view:
<?php $this->Paginator->options(array('url' => '/blog/c/3/other-articles')); ?>
CakePHP Book Section on the PaginatorHelper Options Function: http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html#modifying-the-options-paginatorhelper-uses
I'm trying to use Elements in Cakephp 2.0 without luck. I have a model named Post, a controller named Posts and various views. In the layout I would like to include (for every page/view) a box with the most recent news (say 2).
So I created the element dok-posts.ctp
<?php $posts = $this->requestAction('posts/recentnews'); ?>
<?php foreach($posts as $post): ?>
<div class="Post">
....
In my PostsController I added the function recentnews()
public function recentnews(){
$posts = $this->Post->find('all',array('order' => 'Post.created DESC','limit' => 2));
if ($this->request->is('requested')) {
return $posts;
} else {
$this->set('posts', $posts);
}
}
In my layout, default.ctp I call my element
<?php echo $this->element('dok-posts'); ?>
The problem is that I get this message
Invalid argument supplied for foreach() [APP\View\Elements\dok-posts.ctp, line 9]
Debugging in dok-posts.php, right after the $this->requestAction, gives me an empty line. It seems that the recentnews function is not returning anything (debugging in the function returns an array with the posts found). Can anyone please tell me what am I doing wrong?
Since you found out that the action is actually called,
$posts = $this->requestAction('posts/recentnews');
is working correctly. Here, for clarity and extended configuration options (for later changes to the code), I suggest you to use a Router array instead of an URL
$posts = $this -> requestAction(array(
'controller' => 'posts',
'action' => 'recentnews'
));
Now to your actual problem...
Since you say, it always goes into the else branch,
$this->request->is('requested')
might not work as expected. Try this (it works perfect for me):
if (!empty($this -> request -> params['requested'])) {
return $posts;
}
In your app controller create beforefilter and getNewsElement function.
public function beforeFilter() {
parent::beforeFilter();
$data = $this->getNewsElement();
$this->set('posts',$data);
}
function getNewsElement(){
# Put Post model in uses
$posts = $this->Post->find('all',array('order' => 'Post.created DESC','limit' => 2));
return $posts;
}
dok-posts.ctp
#Remove <?php $posts = $this->requestAction('posts/recentnews'); ?>
<?php foreach($posts as $post): ?>
<div class="Post">
....
In PostsController
public function recentnews(){
$posts = $this->getNewsElement();
$this->set('posts', $posts);
}
This will solve your problem!
Try
<?php $posts = $this->requestAction('/posts/recentnews'); ?>
(note the leading forward slash)
I have followed the example in the Cakephp's guide. From the moment it does not passes the if statement it seems that there is a problem with the control.
$this->request->is('requested')
So I removed the
is->('requested')
adding
->params['requested']
and it works.
Thank you all for your help (especially wnstnsmth for the solution).
Try this
<?php $this->requestAction('/controllerName/functionName');?>
I am using cakePHP and I am trying to get the paginator component to pass the get variables, or passedargs, when you click through to different pages. I have a variety of different search input selectors which "filters" the results returned. This works on first view, but the moment I click on a different page, it shows all of the results.
I have the following setup for my paginator:
// In my controller class:
public $paginate = array('maxLimit' => 10, 'paramType' => 'querystring');
// Within my action method:
$this->paginate = array('conditions' => array(...),
order => array('Model.field ASC'),
'limit' => 20
);
// Calling the paginator:
$results = $this->paginate('Model');
$this->set(compact('results'));
In my view file:
<div class="paging">
<?php
echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));
echo $this->Paginator->numbers(array('separator' => ''));
echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled'));
?>
</div>
EDIT:
From my understanding it's better to use the passedArgs, but I am a little unsure as to how to do this. My $this->passedArgs returns no results, so I am creating the passed parameters within my controller example. I also changed my form from Get to Post:
$this->passedArgs["searchfield"] = $_POST["value"];
It passes the passedArgs now correctly in the pagination strip, but I am unsure as to how to build the paging conditions array now. In most cases users will not select default values example, one of the filters is date from and date to, and then a search input box, if I leave the dates it will still created the argumens and not return any results so in essence my url would be something like:
http://localhost/site/controller/action/page:3/datefrom:0/dateto:0/searchFor:survey
Any assistance?
You can pass by all parameters in the view with:
$this->Paginator->options(array('url' => $this->passedArgs));
or assign the params manually:
$this->Paginator->options(array('url' => array("0", "1")));
befor echoing the paginator
See the CakePHP Cookbook for further Examples
Quick questions
Is there Way to Append a textarea using Cakephp
view code:
<?php echo $ajax->link(
$qnote['Qnote']['subject'],
array(
'controller' => 'qnotes',
'action' => 'view', $qnote['Qnote']['id']
),
array( 'update' => 'Textarea_id')
);
?>
controller Code:
function view($id = null) {
$this->Qnote->id = $id;
$this->set('qnote', $this->Qnote->read());
}
the above code Pulls the information But Replaces the entire Text in the textarea.
Is there a way I can just append the textarea with out removing the existing text in the textarea
if possible can somebody point me in the right direction please.
You can try saving the result of your AJAX request to a hidden field and then having it execute and on page javascript function to simply slap the values from the hidden field to the visible text area.
The AJAX helper lets your specify callback functions, so something like this should work:
<?php echo $ajax->link(
$qnote['Qnote']['subject'],
array(
'controller' => 'qnotes',
'action' => 'view', $qnote['Qnote']['id']
),
array( 'update' => 'Textarea_id_hidden', "complete" => "concat_fields()" )
);
?>
and then the JavaScript in the View
<script type="text/javascript">
function concat_fields() {
$('#Textarea_id').val( $('#Textarea_id').val() . $('#Textarea_id_hidden').val() );
}
</script>
Note: My JavaScript example above assumes you're using JQuery, changes will need to be made if you're not.