I have some difficulties with my ajax pagination linked to a filter. Here's how it should work. The user can access via a specific page to a form. When clicking the submit button, a raw sql request is made in JS and a POST ajax request is achieved to get the results at the bottom of the page with a pagination menu. This part works. But I have some issues with the pagination menu because the links don't work. For example, by clicking the "page 2" link, nothing happens.
Here are the different parts of my code:
Routes
Route::get('articles/filter', 'ArticleController#filterx');
Route::post('articles/request/ajax/articles/filter', 'ArticleController#filtery');
Route::get('articles/request/ajax/articles/filter', 'ArticleController#filtery');
Controller
ArticleController
public function filterx() { // get filter page
return view('filter');
}
public function filtery(Request $request) { // filter ajax function
$articles = Article::paginate(2);
if($request->ajax()) {
// partial view returned in html
return $html = view('filterResults', compact('articles'));
}
}
Views
filter.blade.php
#extends('layouts/app')
#section('title')
Title
#endsection
#section('content')
<div class="container">
<!-- filter -->
<h2>Filter</h2>
<div class="content-card content">
<form method="POST" action="">
<!-- form code... -->
</form>
</div>
<div id="filter-results">
</div>
</div>
#endsection
filterResults.blade.php
#foreach($articles as $article)
<p>{{ $article->name }}</p>
#endforeach
{{ $articles->links() }}
Javascript
$("#submit-button").click(function(e) {
e.preventDefault();
// ajax request (raw mysql request)
var requestQuery = ...; // (quite long) raw request
console.log(requestQuery); // console verification of request
$.ajax({
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
url: '../articles/request/ajax/articles/filter',
type: 'POST',
data: {
request: requestQuery
},
success: function(html) {
$("#filter-results").empty().html(html);
}
});
});
$(window).on('hashchange', function() {
// if hash in url
if (window.location.hash) {
// page contains hash value
var page = window.location.hash.replace('#', '');
if (page == Number.NaN || page <= 0) {
return false;
}
// if ok ->getData returned
else {
getData(page);
}
}
});
$(document).on('click', '.pagination a', function(e) {
e.preventDefault();
$('.pagination li').removeClass('active');
$(this).parent('li').addClass('active');
var url = $(this).attr('href');
var page = $(this).attr('href').split('page=')[1];
getData(page,url);
});
function getData(page,url) {
$.ajax(
{
url: url,
type: 'get',
datatype: 'html',
done: function(data) {
console.log('ok');
$('#filter-results').empty().html(data);
location.hash = page;
},
fail: function(jqXHR, ajaxOptions, thrownError) {
console.log('No response from server');
}
});
}
I don't understand why it is not working, I thing I misunderstood something.
Thanks and have a good day
Laravel uses the page value from the request, or query string, by convention. If you choose not to use that, you can set your own. If following convention, you'd need to append the query string page=# to your url in the ajax request.
The fourth argument of the Builder::paginate is the page number:
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$perPage = $perPage ?: $this->model->getPerPage();
$results = ($total = $this->toBase()->getCountForPagination())
? $this->forPage($page, $perPage)->get($columns)
: $this->model->newCollection();
return $this->paginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
}
You could also define your own page resolver. The default is set in PaginationServiceProvider:
Paginator::currentPageResolver(function ($pageName = 'page') {
$page = $this->app['request']->input($pageName);
if (filter_var($page, FILTER_VALIDATE_INT) !== false && (int) $page >= 1) {
return (int) $page;
}
return 1;
});
Route::get('articles/filter/{page}', 'ArticleController#filter');
public function filter(Request $request, int $page) {
$articles = Article::paginate($page);
}
it's all
Related
I'm working with Laravel 9 and I wanted to make an infinite loader pagination with ajax for my blade.
So at the Controller:
public function index(Request $request)
{
$ques = Question::orderBy('created_at', 'DESC')->where('que_private',0)->paginate(10);
if($request->ajax()){
$view = view('frontend.layouts.partials.infinite',compact('ques'))->render();
return response()->json(['html' => $view]);
}
return view('frontend.index', compact('ques'));
}
And in the index.blade.php:
function loadMoreData(page){
$.ajax({
url: '?page=' + page,
type:'get',
beforeSend: function ()
{
$(".ajax-load").show();
}
})
.done(function(data){
if(data.html == ""){
$('.ajax-load').html("");
return;
}
$('.ajax-load').hide();
$("#post-data").append(data.html);
})
.fail(function(jqXHR,ajaxOptions,thrownError){
alert("Server is not responding");
});
}
And this is infinite.blade.php which ajax loads:
<div id="post-data">
#foreach($ques as $que)
...
#endforeach
</div>
When I test this, the image comes up properly but it returns Server is not responding error alert meaning that .fail(function(jqXHR,ajaxOptions,thrownError){ runs instead.
So what's going wrong here?
How can I solve this issue?
How can I do infinite scrolling in ionic 1 and angular js 1 with dynamic data (Http request)from database ?
HTML :
<ion-view view-title="Playlists">
<ion-content>
<ion-list>
<ion-item class="item-avatar" ng-repeat="item in items">
<h2>{{item.name}} -{{item.id}}</h2>
<p>{{item.iso_code_2}} {{item.iso_code_3}}</p>
</ion-item>
</ion-list>
<div ng-if="hasData">
<ion-infinite-scroll on-infinite="loadMore()" distance="5%">
</ion-infinite-scroll>
</div>
</ion-content>
</ion-view>
Controller.js
This is my angularjs controller. Use a factory named 'CountryService' which is doing http call to get server data. In formdata = {limit:serviceconfig.showlimit,page:page}; I sent limit =10 where I set in config.js service,and set page =1 for the first time.
For the first time GetDefault is called after scrolling GetLoadMore will be called with page =2 and limit=10 with next 10 new data.
angular.module('starter.usercontroller', [])
.controller('UserCtrl', function($scope, CountryService, $ionicModal,
$timeout, $http, serviceconfig, $ionicPopup,$state, ionicDatePicker, $filter) {
$scope.hasData=1; // If data found
$scope.items = [];
CountryService.GetDefault().then(function(items){
$scope.items = items;
});
$scope.loadMore = function() {
CountryService.GetLoadMore().then(function(items){
$scope.items = $scope.items.concat(items);
if(items.length>0)
{
$scope.$broadcast('scroll.infiniteScrollComplete'); // If has data then load more
}
else
{
$scope.hasData=0; // If no more data to load
}
});
};
})
.factory('CountryService',
['$http','serviceconfig',function($http,serviceconfig){
var items = [];
var page =1;
var formdata = {limit:serviceconfig.showlimit,page:page};
return {
GetDefault: function(){
formdata = {limit:serviceconfig.showlimit,page:page};
return $http.post(serviceconfig.serviceUrl+ "all-countries",formdata).then(function(response){
if(response.data.status==1)
{
items = response.data.countries;
}
else
{
items =[];
}
return items;
});
},
GetLoadMore: function(){
formdata = {limit:serviceconfig.showlimit,page:page};
return $http.post(serviceconfig.serviceUrl+ "all-countries",formdata).then(function(response){
page = page+1;
if(response.data.status==1)
{
items = response.data.countries;
}
else
{
items =[];
}
return items;
});
}
}
}]);
Config.js For configuration
In this config.js I set the server url and limit, how many data I want to fetch from server each scroll. 'configService' service I inject in my js controller.
angular.module('starter.configService', [])
.service('serviceconfig',function(){
this.serviceUrl='http://192.168.1.116/ionicserver/service/';
this.showlimit=10;
})
PHP SERVER SITE CODE:
I am using php laravel 5.1. So this is my php controller function for getting county list by below function
public function postAllCountries() // Countries
{
$data = Request::all();
$limit= $data['limit'];
$page = $data['page'];
$offset = ($page - 1) * $limit;
$countries = Country::where('id','>',0)->take($limit)->skip($offset);
$countries = $countries->get()->toArray();
if(!empty($countries))
{
echo json_encode(array('status'=>1,'msg'=>'Successfully Registered','countries'=>$countries));
}
else
{
echo json_encode(array('status'=>0,'msg'=>'No data found'));
}
exit;
}
I want to change deleteMethod to POST method in ng-admin.
For changing createMethod from POST to PUT method I used:
user.createMethod('put');
I want to delete to post method.
user.deleteMethod('post');
The above is not working. Please help me.
if you want to delete selected items then you can go with batchActions and after that create a directory with the name you want and hit the post request.
.batchActions([
'<batch-approvee type="confirm" selection="selection"></batch-approvee>' ])
directive code:
angular.module('myApp').directive('batchApprovee',['Restangular','$q','notification','$state',function(Restangular, $q, notification, $state){
return {
restrict: 'E',
scope: {
selection: '=',
type: '#'
},
link: function(scope, element, attrs) {
scope.icon = attrs.type == 'accept' ? 'glyphicon-thumbs-up' : 'glyphicon-thumbs-down';
scope.updateStatus = function() {
var cItems = {};
var data = [];
var allConfirmData = scope.selection;
allConfirmData.forEach(function(confirmItem,index){
cItems.id = confirmItem._identifierValue;
cItems.status = 2;
data.push(cItems);
cItems = {};
});
var config = {
headers : {
'Content-Type': 'application/json;'
}
}
notification.getBatchApproval(data,config).then(
function(res){
if(res&&res.data){
alert("Inventory Confirmed");
}
},
function(err){
alert(err);
})
}
},
template: ` <span ng-click="updateStatus()"><span class="glyphicon {{ icon }}" aria-hidden="true"></span> Confirm</span>`
};
I'm to trying to store a sort order to each article within a help centre for my new site using Laravel 5 and having a bit of trouble getting it to work. I'm using jQuery UI's .sortable for arranging the elements on the page, and since there are going to be multiple sections throughout the site where areas are sortable, my jQuery script is built in a way for a 'one script for all' purposes. Hence the use of data-* attributes and route name references.
Here is the code I've got so far:
routes.php
Route::post('admin/help-centre/category/{category_id}/section/{section_id}/article/sort-order', 'AdminHelpCentreArticleController#sortOrder');
AdminHelpCentreArticleController.php
public function sortOrder($category_id, $section_id)
{
/* Return ------------------------------------- */
return [
'category_id' => $category_id,
'section_id' => $section_id
];
}
show.blade.php (Admin Article Listing)
<ul id="help-center-articles-sort" class="sortable">
#foreach ($helpCentreArticles as $helpCentreArticle)
<li class="sortable-element" data-sortable-element-id="{{ $helpCentreArticle->id }}">
{{ $helpCentreArticle->title }}
</li>
#endforeach
</ul>
Save Order
scripts.js (includes CSRF Token _token)
var csrfToken = $('meta[name="csrf-token"]').attr('content');
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
if (options.type.toLowerCase() === 'post')
{
options.data += options.data?'&':''; // add leading ampersand if `data` is non-empty
options.data += '_token=' + csrfToken; // add _token entry
}
});
$(document).ready(function() {
$('.sortable').sortable();
$('.sortable-save').on('click', function(e) {
e.preventDefault();
var route = $(this).attr('href'),
sortableID = $(this).attr('data-sortable-id');
var data = $('#' + sortableID + ' .sortable-element').map(function() {
return $(this).attr('data-sortable-element-id');
}).get();
$.ajax({
type: 'POST',
url: route,
dataType: 'json',
data: { id_array: data },
success: function(data) {
console.log(data);
}, error: function(data) {
console.log(data);
},
});
});
});
Everything so far is working in terms of the return response in the console, which is Object {category_id: "1", section_id: "1"}. But no matter what I try, I cannot seem to pass through the data map to the controller to use it.
I've tried a bunch of guesswork since I cannot find a single decent tutorial on AJAX in Laravel 5 anywhere, and I've tried things such as adding a $data parameter to the sortOrder() method, I've tried Input::all() and Request::all but it all returns errors (I'm guessing cause it's not an actual form?).
Once I've got the data to be passed through to the controller I'll be able to save the sort order to the database easily enough. But I can't quite get to that stage, any ideas?
EDIT
I should probably note that I do have a HelpCentreArticle model and a HelpCentreArticleRequest request too, here's some of the code from each file in case they are also needed:
HelpCentreArticle.php
class HelpCentreArticle extends Model {
protected $fillable = [
'category_id',
'section_id',
'title',
'content',
'excerpt',
'is_visible',
'sort_order',
'created_by',
'updated_by',
];
}
HelpCentreArticleRequest.php
class HelpCentreArticleRequest extends Request {
/* Authorization ------------------------------ */
public function authorize()
{
return true;
}
/* Validation rules --------------------------- */
public function rules()
{
$rules = [
'title' => 'required|min:3',
'content' => 'required|min:10',
];
return $rules;
}
}
I wasn't sure if I needed to add HelpCentreSectionRequest $request as the last parameter of the sortOrder() method, so I could use $request->all() but it just returns a 422 (Unprocessable Entity) in the console log.
So it appears that the correct way was to use Input::get('id_array'); instead of $_POST['id_array'];, which I tried, but when I originally tried this I wasn't including use Input; at the top of my controller, as I thought this was already accessible, but it wasn't.
Adding use Input;, and using Input::get(); is now working as expected.
Here is the updated code:
AdminHelpCentreArticleController.php
public function sortOrder($category_id, $section_id)
{
/* Query Select ------------------------------- */
$helpCentreCategory = HelpCentreCategory::findOrFail($category_id);
$helpCentreSection = HelpCentreSection::findOrFail($section_id);
/* Variables ---------------------------------- */
$id_array = Input::get('id_array');
$sort_order = 1;
/* Query Update ------------------------------- */
foreach($id_array as $id) {
$helpCentreArticle = HelpCentreArticle::where('id', $id)->first();
$helpCentreArticle->sort_order = $sort_order;
$helpCentreArticle->save();
$sort_order++;
}
/* Return ------------------------------------- */
return ['success' => true];
}
Then you can obviously access success for an if else statement in your jQuery to manipulate the page.
My implementation of UI sortable with Laravel
index.blade.php
...
#foreach($photos as $photo)
<tr data-sortable="{{ $photo->pivot->position }}" data-id="{{ $restaurant->id }}" data-photo-id="{{ $photo->pivot->photo_id }}">
<td>
<i class="fa fa-sort" aria-hidden="true"></i>
</td>
...
</tr>
#endforeach
<script type="text/javascript">
$("#sortable-ui tbody").sortable({
helper: fixHelper,
update: function(event, ui) {
$("#sortable-ui tbody tr").each(function(index){
console.log($(this).data('id')+', '+(index+1));
$.ajax({
url: '{{ route('owner.photo.update.position') }}',
type: 'POST',
data: 'restaurant_id='+$(this).data('id')+'&photo_id='+$(this).data('photo-id')+'&position='+(index+1)
})
.done(function (response) {
console.log(response);
})
.fail(function (jqXhr) {
console.log(jqXhr);
});
});
}
}).disableSelection();
</script>
scripts.js
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
AjaxController.php
public function updatePhotoPosition(Request $request)
{
$restaurant = $this->restaurantRepository->getById($request->get('restaurant_id'));
$photoId = $request->get('photo_id');
$photo = $restaurant
->photos()
->wherePivot('photo_id', $photoId)
->first();
$photo->pivot->position = $request->get('position');
$photo->pivot->save();
}
I'm completely puzzled to why this happens, I've been messing on this for a few hours and I'm going crazyyyy! I am trying to update my DB when a checkbox is toggled on or off. The success response works if my PHP function I'm calling is empty, but fails whenever I add PHP. Note I'm on Laravel 3, and I've tried enabling or disabling CSRF filtering, no luck.
My JS:
$seenTD = $('td.seen_by_user');
$seenTD.each(function() {
$this = $(this);
var $seenLabel = $this.find('label');
var $seenInput = $this.find(':checkbox');
$seenInput.change(function() {
var _csrf = $('input[name="csrf_token"]').val();
var chkName = $(this).attr('name');
var checkVal = $(':checkbox[name='+chkName+']').prop('checked'); //true or false
var id = $this.find('input[name="reminder_id"]').val();
$.ajax({
url: 'update',
type: 'POST',
data: 'seen='+checkVal+'&reminder_id='+id+'&csrf_token='+_csrf,
success: function(data) {
console.log(data);
if($seenInput.is(':checked')) {
$seenLabel.removeClass('unchecked').addClass('checked');
$seenLabel.find('span').text('Oui');
}
else {
$seenLabel.removeClass('checked').addClass('unchecked');
$seenLabel.find('span').text('Non');
}
}
});
});
});
My PHP
public function post_update() {
$request = Request::instance();
$content = $request->getContent();
$id = $content['id'];
$seen = $content['seen'];
if($seen == 'true') {
$seen = 1;
}
if($seen == 'false') {
$seen = 0;
}
DB::table('reminders')->where('id', '=', $id)->update(
array(
'seen_by_user' => $seen
));
}
For the sake of maybe helping someone, as this is my first working AJAX, I'll explain how I got it to work, as well as supply working code. I'm not claiming this is the best way to do it, so if anyone has their word to say, don't hesitate :)
There were multiple issues, from Javascript insconsistency returning the row ID I needed for the database update, to the PHP function, and the way I was grabbing the POST data.
To get it to work, I played on Fiddler, retrieved the error message that Laravel throws at me. And I could debug from there :)
My working code is :
JS:
$('td.seen_by_user :checkbox').change(function() {
$this = $(this);
var $label = $this.siblings('label');
var id = $this.attr('data-id');
var _csrf = $this.siblings('input[name="csrf_token"]').val();
var value = $this.prop('checked');
$.ajax({
url: 'update',
type: 'POST',
data: {"seen_by_user": value, "id": id, "csrf_token": _csrf},
success: function(data) {
if($this.is(':checked')) {
$label.removeClass('unchecked').addClass('checked');
$label.find('span').text('Oui');
}
else {
$label.removeClass('checked').addClass('unchecked');
$label.find('span').text('Non');
}
}
});
});
PHP
function post_update() {
$id = $_POST['id'];
$seen = $_POST['seen_by_user'];
if($seen == 'true') {
$seen = 1;
}
if($seen == 'false') {
$seen = 0;
}
$update_reminder = DB::table('reminders')->where('id', '=', $id)->update(
array('seen_by_user' => $seen));
}
And my HTML (Blade Template from Laravel, where {{ }} brackets are simply echo's, and #foreach is a )
#foreach ($reminders as $reminder)
...
<td class="seen_by_user">
<form class="ajax" action="update" method="POST">
{{ Form::token() }}
{{ Form::checkbox('seen_'.$reminder->id, 1, $reminder->seen_by_user, array('id' => 'seen_'.$reminder->id, 'data-id' => $reminder->id)) }}
<label class="seen {{ ($reminder->seen_by_user == 1 ? 'checked' : 'unchecked' ) }}"for="{{ 'seen_'.$reminder->id }}"><i class="read"></i><span>{{ ($reminder->seen_by_user == 1 ? 'Oui' : 'Non') }}</span></label>
</form>
</td>
...
#endforeach
data should be an object like this
data: {"seen": checkVal, "reminder_id": id, "csrf_token": _csrf},
The $.ajax method will take care of the presentation and transmission.