Load more data on page scroll or click using Jquery Ajax in Laravel

You have already known about Twitter and Facebook. The timeline page loads data when you reach at the end of page. This way, server doesn't need to load all data in single view and provide smooth user experience.

In this article, we will create a Laravel application. In this application, we will load posts when user reaches at the end of page. We will also create a second way to load data when user clicks a button, 'Load more posts'.

We will go through step by step. So let's start from creating new Laravel application.

Step 1: Create a new Laravel application.

First Open the Terminal or Command Prompt and run the following command to create a new Laravel application.

composer create-project laravel/laravel posts

After the application created, change directory to project.

cd posts

Step 2: Database configuration

Now in this step, change database credentials in .env file according to your MySQL.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=posts
DB_USERNAME=root
DB_PASSWORD=root

Step 3: Create migration for posts table using artisan command.

php artisan make:migration create_posts_table

This will create migration file at database/migrations directory. Open the file and add two columns for posts table.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

After you have added two fields, save file and run migrate command.

php artisan migrate

Step 4: Create Post model

You will also need to create model class for getting data. Run the below command to create model class at app/Models directory.

php artisan make:model Post

Step 5: Create controller class

Now in this step, create a controller class which defines method to load view and fetch data.

php artisan make:controller PostController

This will create controller class app/Http/Controllers/PostController.php file. Open file and add new method in it.

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * view post page
     *
     * @return void
     */
    public function post(Request $request)
    {
        $posts = Post::paginate(8);

        if ($request->ajax()) {
            $html = '';

            foreach ($posts as $post) {
                $html.='<div class="mt-5"><h1>'.$post->title.'</h1><p>'.$post->body.'</p></div>';
            }

            return $html;
        }

        return view('post');
    }
}

Step 6: Add new route

To handle view, you also need to create a route in routes/web.php.

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;

Route::get('post', [PostController::class, 'post'])->name('post');

Step 7: Create a blade view

To view the posts, we also need to create a blade file post.blade.php file in resources/views directory. Add the below HTML view in it.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Posts</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <style type="text/css">
        main > .container {
            padding: 60px 15px 0;
        }
    </style>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
            <div class="container-fluid">
                <a class="navbar-brand" href="#">Fixed navbar</a>
            </div>
        </nav>
    </header>
    <main class="flex-shrink-0">
        <div class="container" id="post">
            {{-- here loads posts --}}
        </div>
        <p class="text-center loading">Loading...</p>
    </main>
    <script type="text/javascript">
        var paginate = 1;
        loadMoreData(paginate);
        $(window).scroll(function() {
            if($(window).scrollTop() + $(window).height() >= $(document).height()) {
                paginate++;
                loadMoreData(paginate);
              }
        });
        // run function when user reaches to end of the page
        function loadMoreData(paginate) {
            $.ajax({
                url: '?page=' + paginate,
                type: 'get',
                datatype: 'html',
                beforeSend: function() {
                    $('.loading').show();
                }
            })
            .done(function(data) {
                if(data.length == 0) {
                    $('.loading').html('No more posts.');
                    return;
                  } else {
                    $('.loading').hide();
                    $('#post').append(data);
                  }
            })
               .fail(function(jqXHR, ajaxOptions, thrownError) {
                  alert('Something went wrong.');
               });
        }
    </script>
</body>
</html>

If you want to load data on button click, Then it is also easy. You only need to call loadMoreData() Javascript function on button click. Here is post.blade.php file if you want to add more post on button click.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Posts</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <style type="text/css">
        main > .container {
            padding: 60px 15px 0;
        }
    </style>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
            <div class="container-fluid">
                <a class="navbar-brand" href="#">Fixed navbar</a>
            </div>
        </nav>
    </header>
    <main class="flex-shrink-0">
        <div class="container" id="post">
            {{-- here loads posts --}}
        </div>
        <div class="text-center m-3">
            <button class="btn btn-primary" id="load-more" data-paginate="2">Load more...</button>
            <p class="invisible">No more posts...</p>
        </div>
    </main>
    <script type="text/javascript">
        var paginate = 1;
        loadMoreData(paginate);

        $('#load-more').click(function() {
            var page = $(this).data('paginate');
            loadMoreData(page);
            $(this).data('paginate', page+1);
        });
        // run function when user click load more button
        function loadMoreData(paginate) {
            $.ajax({
                url: '?page=' + paginate,
                type: 'get',
                datatype: 'html',
                beforeSend: function() {
                    $('#load-more').text('Loading...');
                }
            })
            .done(function(data) {
                if(data.length == 0) {
                    $('.invisible').removeClass('invisible');
                    $('#load-more').hide();
                    return;
                  } else {
                    $('#load-more').text('Load more...');
                    $('#post').append(data);
                  }
            })
               .fail(function(jqXHR, ajaxOptions, thrownError) {
                  alert('Something went wrong.');
               });
        }
    </script>
</body>
</html>

Step 8: Create fake post data.

You will also need to create fake data. You can use Laravel factory to create dummy data. Or run the below SQL query multiple tiles in MySQL command line.

INSERT INTO `posts` (`id`, `title`, `body`, `created_at`, `updated_at`) VALUES (NULL, 'This is post heading', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod ntempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, nquis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo nconsequat. Duis aute irure dolor in reprehenderit in voluptate velit esse ncillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non nproident, sunt in culpa qui officia deserunt mollit anim id est laborum.', NULL, NULL);

Now everything is complete on code side. Run the Laravel server using artisan command.

php artisan serve

In your browser, go to http://localhost:8000/post and scroll through page.

Conclusion

This way, you can create smooth user experience without loading page. If you like the article, please like our Facebook page and follow us on Twitter.

Was this article helpful?

0 out of 0 person found this article helpful.

Leave a comment

Or

No Comment