eventlistener's avatar

Which javascript framework or library to choose for Laravel in this scenario?

I want to do pagination without refreshing the page. What libraries or framework should I choose? I know that this should possible with advanced frameworks such as VueJS or ReactJS. There's a lot of information out there on updating without refreshing the page. However, pagination makes this issue a bit more challenging.

My requirements are as follows:

  • I want to stay as close to PHP as possible.
  • Any JS framework should be light weight.
  • The library or framework should not cause my whole project to be adjusted heavily

So I came up with old jQuery.

My questions:

  • nowadays, is there anything better (modern) than jQuery to use for pagination and displaying results without refreshing the page?
  • what is a general workflow for implementing asynchronous javascript in Laravel?

Let me give an example of what I mean by workflow and what hurdles I encounter along the way when trying to implement jQuery in Laravel.

First hurdle: When I send JSON search results to the browser, then jQuery needs to dynamically add the DIVs. The code becomes garbled or not pretty, like this:

            html += "<div class=\"col-lg-4 col-md-6 col-sm-6 col-12\">";
            html += "<a href=\"{{ route('searchByUserId', ['id' => $user->id]) }}\">";
            html += "<div class=\"members-box\">";
            html += "<div class=\"members-img\">";
            html += "<img src=\"" + value.photo + "\" alt=\"Profile picture of "  + value.first_name + " " + value.last_name + "\" class=\"img-fluid\">";
			$('.search-results').html(html);

Second hurdle, dynamic jQuery makes my software become "javascript first", meaning that if for any reason javascript doesn't work, then PHP still delivers JSON to the browser, thus my application doesn't work properly.

Third hurdle: if I make my application "PHP first", then I get code duplication. Because I have to send data to the browser with PHP the usual way (with browser refresh) and then send it one more time with JSON so that jQuery can do its thing. The HTML will have to be defined twice.

Fourth hurdle: when a user clicks on the next page, then the paging information needs to be updated in the GUI as well in several places (1: "Your search returned 300 results" 2: "Page 4 of 11". 3: current page highlighted). Should I create a separate route for pages? How does that work exactly? Besides, as explained before in the previous hurdle, I will get code duplication here as well.

Fifth hurdle: Laravel contains pagination out of the box. However, if I want to change its CSS, for example to highlight the current page, I cannot think of any way to do that.

Thanks in advance for your help!!

0 likes
4 replies
LaryAI's avatar
Level 58

There are several options for implementing pagination without refreshing the page in Laravel. One lightweight option is to use the Axios library for making asynchronous requests and handle the pagination logic on the server-side using Laravel's built-in pagination functionality. Here is a general workflow for implementing asynchronous JavaScript in Laravel using Axios:

  1. Create a route in your Laravel application that returns a JSON response with the paginated data. For example:
Route::get('/search', function () {
    $results = DB::table('my_table')->paginate(10);
    return response()->json($results);
});
  1. In your JavaScript code, use Axios to make a GET request to the above route and handle the response. For example:
axios.get('/search')
    .then(response => {
        // Handle the response data, e.g. update the DOM with the new results
    })
    .catch(error => {
        // Handle any errors
    });
  1. To handle pagination, you can add query parameters to the GET request to specify the page number and number of results per page. For example:
axios.get('/search', {
    params: {
        page: 2,
        perPage: 10
    }
})
  1. To update the pagination information in the GUI, you can include the pagination data in the JSON response from the server and use JavaScript to update the relevant elements in the DOM. For example:
{
    "data": [...],
    "links": {
        "first": "/search?page=1",
        "last": "/search?page=5",
        "prev": "/search?page=1",
        "next": "/search?page=3"
    },
    "meta": {
        "current_page": 2,
        "from": 11,
        "last_page": 5,
        "path": "/search",
        "per_page": 10,
        "to": 20,
        "total": 50
    }
}
  1. To customize the pagination CSS, you can override the default Laravel pagination views or create your own custom views. See the Laravel documentation for more information on customizing pagination views.

Overall, using Axios and Laravel's built-in pagination functionality can provide a lightweight and efficient solution for implementing pagination without refreshing the page.

m7vm7v's avatar

There are a lot of ways to achieve this. For me the easiest way was to have a Livewire component with the Laravel native pagination and alpineJS -

    public function render()
    {
        return view('livewire.social', [
            'feeds' => Feed::query()
                ->paginate($this->perPage)
        ]);
    }

    public function loadMore()
    {
        $this->perPage += $this->perPage;
    }

Then in the blade I have -


<div>
    @forelse ($feeds as $feed)
        the feed
    @empty
        <div class="font-medium text-gray-900 whitespace-nowrap text-center">
            {{ __('No social feeds added yet.') }}
        </div>
    @endforelse

    <div
        x-data="{
            observe () {
                let observer = new IntersectionObserver((entries) => {
                    entries.forEach(entry => {
                        if (entry.isIntersecting) {
                            @this.call('loadMore')
                        }
                    })
                }, {
                    root: null
                })

                observer.observe(this.$el)
            }
        }"
        x-init="observe"
    ></div>

    <div class="text-center">
        @if($feeds->hasMorePages())
            <button wire:click.prevent="loadMore">{{ __('Load more') }}</button>
        @endif
    </div>
</div>

If you remove the observer then you will end up with the "Load more" button on the end, which on click will load more results. The observer checks when the block is in view and then triggers the method automatically.

eventlistener's avatar

@m7vm7v Thanks for your reply. If I use Livewire only the search results page, does it require changes throughout the entire project? I don't have any experience with Livewire, but I'm willing to look into it.

m7vm7v's avatar

@eventlistener no, it should be straightforward to implement just that without interrupting any other code. Livewire is components based so it actually will help you to separate that logic gracefully.

Please or to participate in this conversation.