skip to Main Content

I am currently trying to create a Blade page that shows 3 boxes, and below that, a list of notifications that is retrieved from the backend. To load the list of notifications, I’m trying to make an ajax call to an API endpoint.

My homepage blade:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" 
    href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" 
    integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" 
    crossorigin="anonymous">
</head>
<body>
    <div class="card" style="width: 18rem;">
      <div class="card-body">
        <h5 class="card-title">Total revenue (30 days)</h5>
        <p class="card-text">{{ $totalRevenue }}</p>
      </div>
    </div>
    <div class="card" style="width: 18rem;">
      <div class="card-body">
        <h5 class="card-title">Total followers (30 days)</h5>
        <p class="card-text">{{ $totalFollowers }}</p>
      </div>
    </div>
    <div class="card" style="width: 18rem;">
      <div class="card-body">
        <h5 class="card-title">Top 3 item sales (30 days)</h5>
        @foreach($topItemSales as $topItemSale)
          <p class="card-text"> 
            {{ $topItemSale->item_name }}
          </p>
          <p class="card-text"> 
            {{ $topItemSale->total }}
          </p>
        @endforeach
      </div>
    </div>
    <div id="item-lists">
        @include('layouts.notificationlist')
    </div>
    <script
    src="https://code.jquery.com/jquery-3.3.1.js"
    integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
    crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" 
    integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" 
    crossorigin="anonymous"></script>

    <script type="text/javascript">
    $(window).on('hashchange', function() {
        if (window.location.hash) {
            var page = window.location.hash.replace('#', '');
            if (page == Number.NaN || page <= 0) {
                return false;
            }else{
                getData(page);
            }
        }
    });

    $(document).ready(function()
    {
        $(document).on('click', '.pagination a',function(event)
        {
            $('li').removeClass('active');
            $(this).parent('li').addClass('active');
            event.preventDefault();
        
            var myurl = $(this).attr('href');
            var page=$(this).attr('href').split('page=')[1];
            
            getData(page);
        });
    });

    function getData(page){
        $.ajax({
            url: '?page=' + page,
            type: "get",
            datatype: "html",
        })
        .done(function(data){
            $("#item-lists").empty().html(data);
            location.hash = page;
        })
        .fail(function(jqXHR, ajaxOptions, thrownError){
              alert('No response from server');
        });
    }

    </script>
</body>
</html>

My notificationlist blade (the list of notifications I want to show)

<table class="table table-bordered">
<tbody>
    @foreach($notifications as $notification)
        <li class="list-group-item">{{ $notification['msg'] }}</li>
          <input type="checkbox" class={{ $notification['identifier'] }} name={{ $notification['id'] }} value={{ $notification['is_read'] }}">
        <br></br>
    @endforeach
</tbody>
</table>


{!! $notifications->render() !!}

My routes/web.php:

<?php

use AppHttpControllersLoginController;
use AppHttpControllersUserController;
use AppHttpControllersNotificationController;
use IlluminateSupportFacadesRoute;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

Route::group( ['middleware' => 'auth' ], function()
{
    Route::get('/home', [UserController::class, 'index'])->name("index");
    Route::post('/update', [UserController::class, 'update'])->name("update");
    Route::get('/home/page', [NotificationController::class, 'index'])->name('index');
});

Route::get('login', [LoginController::class, 'index'])->name('login');
Route::get('login/{provider}', [LoginController::class, 'redirectToProvider']);
Route::get('{provider}/callback', [LoginController::class, 'handleProviderCallback']);

My UserController:

<?php

namespace AppHttpControllers;

use AppModelsUser;
use IlluminateHttpRequest;
use AppServicesFollowerService;
use AppServicesMerchSaleService;
use AppServicesRevenueService;
use AppServicesNotificationService;
use Auth;

class UserController extends Controller
{
    public function __construct(
        protected FollowerService $followerService,
        protected MerchSaleService $merchSaleService,
        protected RevenueService $revenueService,
        protected NotificationService $notificationService
    ) {
        $this->followerService = $followerService;
        $this->merchSaleService = $merchSaleService;
        $this->revenueService = $revenueService;
        $this->notificationService = $notificationService;
    }
    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        $totalFollowers = $this->followerService->getTotalFollowers(30, Auth::id());
        $topItemSales = $this->merchSaleService->getTopItems(30, 3, Auth::id());
        $totalRevenue = $this->revenueService->getTotalRevenue(30, Auth::id());
        return view('layouts/home')
            ->with('totalFollowers', $totalFollowers)
            ->with('topItemSales', $topItemSales)
            ->with('totalRevenue', $totalRevenue);
    }
}

My NotificationController:

<?php

namespace AppHttpControllers;

use AppModelsUser;
use IlluminateHttpRequest;
use AppServicesFollowerService;
use AppServicesMerchSaleService;
use AppServicesRevenueService;
use AppServicesNotificationService;
use Auth;

class NotificationController extends Controller
{
    public function __construct(
        protected FollowerService $followerService,
        protected MerchSaleService $merchSaleService,
        protected RevenueService $revenueService,
        protected NotificationService $notificationService
    ) {
        $this->followerService = $followerService;
        $this->merchSaleService = $merchSaleService;
        $this->revenueService = $revenueService;
        $this->notificationService = $notificationService;
    }
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {
        $notifications = $this->notificationService->getNotifications(100, Auth::id(), null);
        $notificationStrings = [];
        foreach ($notifications as $notification) {
            if ($notification->identifier == 'merch_sale') {
                array_push($notificationStrings, [
                    'id' => $notification->id,
                    'identifier' => $notification->identifier,
                    'is_read' => $notification->is_read,
                    'msg' => $notification->buyer.' bought '.$notification->amount.$notification->item_name.' from you for '.$notification->price.' '.$notification->currency.' at '.$notification->created_at
                ]);
            }
            elseif ($notification->identifier == 'follower') {
                array_push($notificationStrings, [
                    'id' => $notification->id,
                    'identifier' => $notification->identifier,
                    'is_read' => $notification->is_read,
                    'msg' => $notification->name.' followed you at '.$notification->created_at
            ]);
            }
            elseif ($notification->identifier == 'subscriber') {
                array_push($notificationStrings, [
                    'id' => $notification->id,
                    'identifier' => $notification->identifier,
                    'is_read' => $notification->is_read,
                    'msg' => $notification->name.' (Tier '.$notification->subscription_tier.') subscribed to you at '.$notification->created_at
                ]);
            } 
            elseif ($notification->identifier == 'donation') {
                array_push($notificationStrings, [
                    'id' => $notification->id,
                    'identifier' => $notification->identifier,
                    'is_read' => $notification->is_read,
                    'msg' => $notification->donator.' donated '.$notification->amount.' '.$notification->currency.' to you at '.$notification->created_at
                ]);
            }
        }
        if ($request->ajax()) {
            return view('notificationlist', $notificationStrings);
        }
        return view('notifications', $notificationStrings);
    }
}

However, when I load the page, it says that the $notifications variable is undefined in the notificationlist blade.

Why would this be the case? I thought in my Ajax, upon document ready, it should send a request to the /home/page endpoint, which should return back the $notification data?

I’ve also tried inserting console.log statements in the blade template, but none of them print in any of the JS functions.

Thanks!

2

Answers


  1. Chosen as BEST ANSWER

    I changed the layout a bit and fixed the code. Instead of pagination, I just show a Next 100 and Prev 100 button, and set the script in the homepage blade to be

        <script type="text/javascript">
        function getData(event, created_at){
            event.preventDefault();
            console.log(created_at);
            $.ajax({
                url: '/home/next',
                type: "get",
                datatype: "html",
                data: {created_at: created_at}
            })
            .done(
              function(data) {
                $('#item-lists').empty();
                console.log(data);
                $('#item-lists').html(data);
              }
            )
            .fail(function(jqXHR, ajaxOptions, thrownError){
                  alert('No response from server');
            });
        }
    
        </script>
    

    The buttons are defined as

        <button class="btn btn-outline-success" onclick="getData(event, '{{ $notifications[count($notifications) - 1]['created_at'] }}')">Prev 100</Button>
        <button class="btn btn-outline-success" onclick="getData(event, '{{ $notifications[count($notifications) - 1]['created_at'] }}')">Next 100</Button>
    

    Although now, I'm having some issues refreshing the $notifications variable after the AJAX call


  2. You are getting a few different paradigms mixed up.

    If you want to mix javascript and blade my suggestion is to use the amazing livewire, which is amazing and will allow you to do what you are suggesting.

    As it stands what you are trying to do wont work, you are mixing server side code (blade) with client side code (javascript) and really the two never meet. By the time your javascript runs it is not looking at a blade page (even if it was it wouldnt know what to do with it), it is looking at a plain html page.

    If you wish to retireve data from teh server in your javascript and use it to render on your page, you will need to write javascript rendering code or us a javascript template engine, but I suggest you take a look at livewire.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search