AJAX pagination with Laravel

51,708

Solution 1

I'm not very familiar with pagination in Laravel but judging from the links you listed it doesn't look too hard. This code is untested though...

$('#pagination a').on('click', function(e){
    e.preventDefault();
    var url = $(this).attr('href');
    $.post(url, $('#search').serialize(), function(data){
        $('#posts').html(data);
    });
});

Update

In case the pagination links are wrong (like the were for the OP) you have to build the url by yourself.
Just take the url you want and add ?page=#number to it.

// page being the page number stripped from the original link
var url = $('#search').attr('action')+'?page='+page;

Solution 2

I am using following js for getting data on href click.

// Your Local url 
var Url = 'laraveltestproject/laravelpagination';

$('#ajaxContent').load("Url");

$('.pagination a').on('click', function(event) {

    event.preventDefault();
    if ($(this).attr('href') != '#') {
        $('#ajaxContent').load($(this).attr('href'));
    }
});

For Complete example you can visit the http://www.tutsway.com/laravel-ajax-pagination-example.php.

Solution 3

I have the perfect tool for the job. Please check out this repo https://github.com/themightysapien/ajaxtable

Please read the docs it is very easy to use and is specially made for laravel. All you need to do is return your results as following example.

return Response::json(array(
              'data'=> View::make('only_table_row_view', compact('collection')->render(),
              'pagination'=>(string) $collection->links()
              ));

Required files are add

<link rel="stylesheet" href="css/ajaxtable.css">
<script src="js/plugins.js"></script>
$(".yourtable").ajaxtable();

Initialize your ajax url through data-requestUrl attribute in your table. Add a id="paginationWrapper" div in your page where you want your pagination to appear.

If you have any problem run the repo in your local server and see the source for html markups and plugin options.

Solution 4

Example for post in a blog, solve paginate reload on delete button: (sinple foreach but you must give a id to panel and button and a class to button and use $post->id to define all)

The trick at last is not call the view/controller that uses pagination() but the view change with javascript as you want.

      @foreach($posts as $post)
    <div id="panel{{$post->id}}" class="panel panel-default">
      <div class="panel-body">
        {!! $post->content !!}
      </div>
      <div class="panel-footer">
        <span class="label label-default"><span class="glyphicon glyphicon-time"></span> creado {{$post->created_at->diffForHumans()}}</span>
        <span class="label label-default"><span class="glyphicon glyphicon-time"></span> modificado {{$post->updated_at->diffForHumans()}}</span>
        <span class="label label-success">autor: {{ imagica\User::find($post->user_id)->name}}</span>
        @if(Auth::user()->id === $post->user_id)

          <form method="post" style="position:relative; top:-25px;">
            <button class="btn btn-danger btn-sm pull-right destroy" id="{{$post->id}}" type="button" >eliminar</button>
          </form>

          <form action="{{ action('PostsController@edit', $post->id) }}" method="get" style="position:relative; top:-25px;">
            <button class="btn btn-warning btn-sm pull-right" type="submit" >Editar</button>
            {{-- {{ csrf_field() }} --}}
          </form>
        @endif
      </div>
    </div>
  @endforeach

at last of the view javascript:

$(function(){
$(".destroy").on("click", function(){
  var vid = $(this).attr("id");
  var v_token = "{{csrf_token()}}";
  var parametros = {_method: 'DELETE', _token: v_token};
  var archivo = "http://imagica.app/posts/" + vid + "";
  $.ajax({
     type: "POST",
     url: archivo,
     data: parametros,
     success: function(data){
       $('#panel'+ data).hide();
       location.reload();
     }
  });
});
});

In controller destroy function (note you send $post->id as data to ajax, it is used to define selectors to hide panel of post you delete):

    public function destroy($id)
{
  $post= Post::find($id);
  $article_id= $post->article_id;
  $article= Article::find($article_id);
  $msg = session()->flash('message', "Post eliminado.");
  $post-> delete();
  $data= $post->id;
  return $data;
}

In javascript last function "location.reload()" is in order to charge flash message.

Share:
51,708
JasonK
Author by

JasonK

Just another enthusiast!

Updated on June 30, 2020

Comments

  • JasonK
    JasonK almost 4 years

    I have this view called posts.blade.php which gets included in home.blade.php:

    <div id="posts">
        @foreach ($posts as $post)
            <div class="list-item clearfix">
                <div class="content">
                    <img src="{{ URL::to($post->thumbnail) }}" alt="" />
                    <h1>{{{ $post->title }}}</h1>
                </div>
                <div class="score">{{ $post->rating }}</div>
            </div>
        @endforeach
        <div id="pagination">{{{ $posts->links() }}}</div>
    </div>
    

    When a user searches for certain posts, the controller's postSearch() function returns a JSON response:

    function postSearch() 
    {
        $posts = $posts->select(...)->where(...)->orderBy(...)->paginate(5); //Search posts
    
        return Response::json(View::make('includes.posts', ['posts' => $posts])->render());
    }
    

    And jQuery appends the HTML on the #posts div:

    $('#search').submit(function(e) {
        e.preventDefault();
        var form = $(this);
    
        $.post(form.attr('action'), form.serialize(), function(data) {
            $('#posts').html(data);
        });
    });
    

    This works perfect. But now when I click on a pagination link, the page reloads and my search results are gone (obvious). How do I paginate these posts? I've read this, this and this article, but I don't understand how to implement it.

    Edit

    This is my jQuery for the pagination so far:

    $('#posts').on('click', '.pagination a', function(e) {
        e.preventDefault();
        var url = $(this).attr('href'),
            page = url.split('page=')[1],
            data = $('#search').serializeArray();
    
        data.push({page: page}); // Add page variable to post data
        console.log(data);
    
        $.post($('#search').attr('action'), data, function(data) {
            $('#posts').html(data['posts']);
        });
    });
    

    This is data is being send when I click on a pagination link (page 2):

    enter image description here

    Unfortunately nothing happens, the posts from page 1 keep showing.

  • JasonK
    JasonK over 9 years
    Please see my edit. I tried your code but it returns the HTML of my home page, because the href of a pagination link is http://localhost:8080/laravel/laravel/public?page=2.
  • lukasgeiter
    lukasgeiter over 9 years
    Try sending the page number via GET. I did some testing and it looks like Laravel doesn't pick up the POST parameter. Just append it to the action url: $('#search').attr('action')+'?page='+page
  • JasonK
    JasonK over 9 years
    Let me point out that the if ($(this).attr('href') == '#') check isn't necessary since the current pagination link isn't clickable.
  • lukasgeiter
    lukasgeiter over 9 years
    Thanks, removed it... Probably it was clickable in an earlier version of the framework