CakePHP 3 AJAX with Pagination - cakephp

I am new to CakePHP. I have installed CakePHP 3.2.10.
I have implemented simple AJAX calls. I have also implemented pagination in normal view.
Now I want to show records, loading with AJAX and using pagination.
Can anyone guide me how to go about doing this?
I have referred to the cookbook but did not get proper information.
Do I create a normal action and view with pagination code ?

Simply, you can use liveQuery Javascript library. you can download from here
And add this library code in your CakePHP template layout in
Wrap your listings and pagination links in div tag apply id="wrapper".
add this function in common javascript code which must be load in
page end before end of body tag
Add Below Code in Javascript
function ajaxPageLoader(request_url) {
console.log("Content loading from : "+request_url);
$("#wrapper").load(request_url + " #wrapper", function() {
window.history.pushState({}, "", request_url);
console.log("Content loaded");
});
}
$(document).ready(function(){
$('your_pagination_link_selector').livequery(function() {
$(this).unbind('click').bind('click', function(e) {
e.preventDefault();
ajaxPageLoader($(this).attr('href'));
return false;
})
});
});

Related

how to set angularjs single page application for social share

I'm trying to set social sharing with SPA using Express.js and AngularJS.
Thing is, I want to share dynamic content, so I'm using angular-facebook-factory to get facebook buttons. Buttons work, params are set, just the image, title and description params that I pass never get to facebook share popup screen.
$scope.shareEvent = function (event) {
console.log('verify values: ', event.image); // works fine!
FacebookService.share({
href: 'http://www.example.com/event/'+event_id+'/', // this value is passed
title: event.title, // Not shown
description: event.desc, // Not shown
image: event.image // Not shown
}, function (response) {
$scope.me = response;
$scope.status = true;
})
}
FB share loads default values (like and ) from http://www.example.com/ and uses set href param (http://www.example.com/event). I tried with method: 'feed' as well, but without success.
I'm supposed to have several different share buttons on the page, so I guess meta og tags are not going to do it...
This is SPA with number of ui-view s, and ui-router using html5 works fine and everything works fine.
This is because Facebook crawlers are unable to render the javaScript!
Angular JS is less friendly when it comes to SEO integration.
Reviewing your code:
$scope.shareEvent = function (event) {
console.log('verify values: ', event.image); // works fine!
FacebookService.share({
href: 'http://www.example.com/event/'+event_id+'/', // this value is passed
title: event.title, // Not shown
description: event.desc, // Not shown
image: event.image // Not shown
}, function (response) {
$scope.me = response;
$scope.status = true;
})
}
you said console.log(event.image); / Works fine
The reason is same, your browser is able to render the JavaScript. But
Facebook crawler is unable to process that javaScript.

How to use `$window.history.back()` to go back in Angular.js?

I am using $window.history.back() to go 1 step back in my Ionic + Angular app.
It has an issue: if my URL is in proper form (http://localhost:8100/jobs.html) then it is working properly, but if my URL is in this form (http://localhost:8100/jobs.html#/category) then it is not working and does not go back.
Here is my function:
$scope.back3=function() {
$window.history.back();
}
I will be thankful for any help.
You need to use window.history.go(-1); in $ionicPlatform.registerBackButtonAction event. It will go back on pressing back button key. below is the example :
app.controller('HomeCtrl', function($ionicPlatform){
$ionicPlatform.registerBackButtonAction(onBackKeyDown, 100);
function onBackKeyDown() {
window.history.go(-1);
}
}
});
For giving back button action on any button use following code:
HTML
<div ng-click="goBack()">Back</div>
JavaScript
$scope.goBack = function() {
window.history.back();
};
If you want to use Ionic Framework history navigation you should also use proper Ionic Framework history object:
Use this if you want to go to the previous view:
$ionicHistory.goBack();
More about it can be found here: $ionicHistory

Server side pagination of AngularJS ng-grid

I am trying to implement this server side pagination example of ng-grid mentioned here http://angular-ui.github.io/ng-grid/ . Unfortunately, I do not quite understand the code.
Here is my situation:
1. Say I have a page which has 2 text boxes and a button. I would like to post the values of these two text boxes to a web service on ng-click of the button. Returned json should be displayed as grid. But the code in the plunker http://plnkr.co/edit/50vJrs?p=preview
$scope.getPagedDataAsync = function (pageSize, page, searchText) {
setTimeout(function () {
var data;
if (searchText) {
var ft = searchText.toLowerCase();
$http.get('largeLoad.json').success(function (largeLoad) {
data = largeLoad.filter(function(item) {
return JSON.stringify(item).toLowerCase().indexOf(ft) != -1;
});
$scope.setPagingData(data,page,pageSize);
});
} else {
$http.get('largeLoad.json').success(function (largeLoad) {
$scope.setPagingData(largeLoad,page,pageSize);
});
}
}, 100);
};
will render the grid on page load (which I do not want). What I dont understand is how to associate the $scope.getPagedDataAsync function with a ng-click?
The html code doesnt have any textbox for searching through the grid even though in the controller they have $scope.filterOptions. How is the search happening the in plunker code?
Wish there was more documentation on the site.
Thank you
In the plunker, the function quoted in your question is immediately invoked:
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
Does commenting out that line have the desired effect?
As for the filter, it's probably there as a convenience so you can add a filter text field yourself. It is defined in an object so you can use a custom directive or ng-include block.

How to set up custom ajax pagination in cakephp 2.*

How do i set up ajax in cakephp without using the default ajax helper? The default ajax helper puts the js code on the page itself, I don't want that. I want it to be set in a seperate js file (ie general.js) instead. How do i do that? I have pagination already set up.
First make sure you have jquery set up. In your default.ctp (View/Layouts/default.ctp) add the following line within the <head> section:
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
In your AppController.php file (Controller/AppController.php) add the following lines
function beforeRender() {
if ($this->request->is('ajax')) {
$this->layout = false;
}
}
This causes the behaviour that when an ajax call is made to an controller action only the view itself is loaded rather than the whole layout.
In your general.js file (webroot/js/general.js) add the following code:
$(document).ready(function(){
ajaxPagingNavigation();
});
function ajaxPagingNavigation() {
$(".paging a").click(function(e) {
$.ajax({
url: $(this).attr('href'),
cache: false
}).done(function( html ) {
$("#content").html(html);
ajaxPagingNavigation();
});
e.preventDefault();
});
}

Intercept cake2 postLink() form posts with jQuery

Has anyone found a way to intercept the default Form::postLink() forms with Jquery?
I would like the form to work without JS (therefore the postLink).
But with JS enabled I want to intercept the post and call it via AJAX.
<?php echo $this->Form->postLink('Delete', array('action'=>'delete', $prospect['Prospect']['id']), array('class'=>'postLink', 'escape'=>false), __('Sure you want to delete # %s?', $prospect['Prospect']['id'])); ?>
generates:
<form action="/admin/prospects/delete/4f61ce95-2b6c-4009-9b89-07e852b0caef" name="post_4f648f773923b" id="post_4f648f773923b" style="display:none;" method="post">
<input type="hidden" name="_method" value="POST"/>
</form>
<a href="#" class="postLink" onclick="if (confirm('Sure you want to delete # 4f61ce95-2b6c-4009-9b89-07e852b0caef?')) { document.post_4f648f773923b.submit(); } event.returnValue = false; return false;">
Delete
</a>
The main problem is that the js is placed inline here. Therefore always triggers even if I try to intercept the click event (or the post event - tried that too):
<script>
$(document).ready(function() {
$('table.list a.postLink').click(function(e) {
e.preventDefault();
alert('Handler for .submit() called.');
// TODO: do ajax request here and return false
return false;
});
});
</script>
So in the end the form always submits normally and redirects - either ignoring any ajax call (catching the form submit) or posting/redirecting regardless of an ajax call just made (catching the click event).
I would like to delete this record via AJAX and - if successful - just remove that table row from DOM. It would be great if one doesn't have to modify all 300+ "delete buttons" in the application for it, though.
If everything fails I could probably still override the FormHelper (extend it and alias it). But I was hoping on a less invasive solution here.
I know this is old, but for any of those searching:
You need to first remove the 'onclick' attribute added to the delete
link.
Then, you add a .click function to the delete link
You need the url (which can be hardcoded or retrieved from the form, which is always the prev element in cakephp Form->postLink
Here is the code:
$(function(){
$('a:contains("Delete")').removeAttr('onclick');
$('a:contains("Delete")').click(function(e){
e.preventDefault();
var form = $(this).prev();
url = $(form).attr("action");
$.post(url);
return false;
});
});
jymboche - what a genius
why didnt i think of it myself?
Well, here is the modified answer of yours:
$(document).ready(function() {
$('table.list a.postLink').removeAttr('onclick');
$('table.list a.postLink').click(function(e) {
e.preventDefault();
if (!confirm('<?php echo __('Sure?')?>')) {
return false;
}
var form = $(this).prev();
var url = $(form).attr("action");
var tr = $(this).closest('tr');
url = url + '.json';
$.post(url).success(function(res) {
if (res.error) {
alert(res.error);
return false;
}
tr.fadeOut(200);
}).error(function() {
alert("Error");
})
return false;
});
});
This is for future reference only.
I will still accept your answer as you gave me the right idea.
jymboche's solution helped me to get to a working answer, but it didn't work fully for me, due to some security cake plugins that I have installed.
Here's what worked for me:
$(function(){
$('a:contains("Delete")').removeAttr('onclick');
$('a:contains("Delete")').click(function(e){
e.preventDefault();
var form = $(this).prev();
var url = $(form).attr("action");
$.ajax({
type: 'POST',
cache: false,
url: url,
data: $(form).serialize(),
success: function(msg) {
// do any extra calls you need to refresh the page
}
});
return false;
});
});
Just an idea, haven't tested it:
<?php echo $this->Form->postLink('Delete', array('action'=>'delete', $prospect['Prospect']['id']), array('class'=>'postLink', 'onclick' => false, 'escape'=>false), __('Sure you want to delete # %s?', $prospect['Prospect']['id'])); ?>
Couple of issues with the current solutions...
First and foremost, the postLink method requires Javascript to be enabled. From Cake's doco:
"Creates an HTML link, but access the url using method POST. Requires javascript to be enabled in browser."
If javascript is disabled, you just get the exact same output - a hidden form, and a link that tries to submit that form with Javascript (but fails, since JS is turned off).
Second, although it will work, it seems weird to use the postLink method, and then use Javacript to undo precisely all the magic that the postLink method creates.
If you want a non-javascript friendly solution, all you have to do is create a regular form that points to the delete method, and put a link below it like this:
<?php echo $this->Form->create('DefaultAvailability', array('url' array('action' => 'delete', $myRecord['ModelName']['id'])));?>
<?php echo $this->Form->end('Delete (no JS)');?>
<a href='#'>Delete (With JS, use AJAX)</a>
Then, for cases when there's no javascript, hide the link below, and the form will work as normal.
For cases when there is javascript, hide the form, and use javascript to make your delete link trigger a submit on your delete form, and handle that submit with ajax.
I've translated the previous jQuery version to Mootools
//We start with foreach, to select all ajax buttons on the page
$$('.ajaxbutton').each(function(item,index){
//remove onClick
item.removeProperty('onclick');
//attach click event
item.addEvent('click', function(e){
//stop click (in my case the form is inside another link)
e.stop();
var form = item.getPrevious();
url = form.get('action');
new Request({
url: url,//url
method: 'post',//method
onSuccess: function(responseText){
//This is not required, we are dimming the button on success
item.getParents()[0].tween('opacity',0.5)
}
}).send();
return false;
});
})

Resources