Peck3277
Peck3277

Reputation: 1423

Laravel Datatables - Multiple tables on one view

I'm using laravel 5.4 and the latest version of yajra/laravel-datatables as a service.

I have it working fine with one datatable on a page. I want to create a dashboard of unrelated tables. Users, products, bookings etc.

I was hoping to have my controller look something like this:

public function index(ProductsDataTable $productDatatable, UsersDataTable $userDatatable)
{    
    $user = Auth::user();

    $products = $user->products;

    return view('admin.dashboard', compact('products', 'user', 'productDatatable', 'userDatatable'));
}

and in my blade do

@section('content')
{!! $productDatatable->table() !!}
{!! $userDatatable->table() !!}
@endsection

@push('scripts')
{!! $dataTable->scripts() !!}
@endpush

However this obviously doesn't work. I'm unsure how to proceed.

I tried to create a route for each datatable but wasn't sure how to reference it from my dashboard controller.

Upvotes: 6

Views: 13324

Answers (3)

Josh D.
Josh D.

Reputation: 333

I'm sure there's a better way of implementing multiple tables in one view, but this is what I came up with after reviewing this. Comments/improvements would be highly appreciated.

Controller

The controller will render the tables once in the index() method but will fetch data from both the getUsers() method or getProducts() method.

// DashboardController.php

public function index(UsersDataTable $usersDataTable, ProductsDataTable $productsDataTable)
{
    return view('dashboard.index', [
        'usersDataTable' => $usersDataTable->html(),
        'productsDataTable' => $productsDataTable->html()
    ]);
}

//Gets Users JSON

public function getUsers(UsersDataTable $usersDataTable)
{
    return $usersDataTable->render('admin.dashboard');
}

//Gets Products JSON

public function getProducts(ProductsDataTable $productsDataTable)
{
    return $productsDataTable->render('admin.dashboard');
}

Routes

Add two extra routes that will be used to fetch Users and Projects data.

// web.php

Route::get('/', 'DashboardController@index')->name('dashboard.index');
Route::get('projects', 'DashboardController@getProjects')->name('dashboard.projects');
Route::get('users', 'DashboardController@getUsers')->name('dashboard.users');

DataTables Service Class

For both the UsersDataTable and ProductsDataTable service classes, include the relevant routes we created above.

// UsersDataTable.php

public function html()
{
    return $this->builder()
                ->minifiedAjax( route('dashboard.users') );
}

View

// dashboard.blade.php

@section('content')

   {!! $productsDataTable->table() !!}
   {!! $usersDataTable->table() !!}

@endsection

@push('scripts')

   {!! $productsDataTable->scripts() !!}
   {!! $usersDataTable->scripts() !!}

@endpush

Upvotes: 6

Naveed Ali
Naveed Ali

Reputation: 369

Step 1: Define a route '/home-page' in web.php/route.php' (depending on the laravel version you are using) that returns the view called 'dt.blade.php'. (we will create this view in step 4)

i.e. Route::get('/home-page', function(){

return view('dt');

});

Step 2: Suppose you want to display two dataTables in 'dt.blade.php' view. (first datatable shows all the students in a school while other shows all the classes in a school)

To do that, you need to create two Builder instances ('Builder' class belongs to DataTables package) in the '/home-page' route's callback function and pass them to the 'dt.blade.php' view . i.e

Route::get('/home-page', function() {

    $student_dt = app(Builder::class)->columns(['id', 'student_name'])->ajax('/show-students-datatable')->setTableId('t1');


    $classes_dt = app(Builder::class)->columns(['id', 'class_name'])->ajax('show-classes-datatable')->setTableId('t2');

    return view('dt', compact('student_dt', 'classes_dt'));

});

Step 3 Now define two more routes in web.php/route.php file:

Route::get('/show-students-datatable', function () {

    return datatables(App\Student::query()->select(['id', 'student_name']))->toJson();

});

Route::get('/show-classes-datatable', function () {

    return datatables(App\Class::query()->select(['id', 'class_name'])))->toJson();

});

Step 4 Define the 'db.blade.php' view, this view show both the dataTables that were passed to it in step 1.

@extends('layouts.master')

    @section('content')

        {{ $student_dt->table() }}
        {{ $classes_dt->table() }}

    @endsection

    @push('scripts')

        {{$student_dt->scripts()}}
        {{$classes_dt->scripts()}}

    @endpush

Upvotes: 1

Peck3277
Peck3277

Reputation: 1423

Submitted a question to the creator of the package. This is his response:

Unfortunately, DataTable service class is designed to handle single instance. However, I think we can make a workaround for it by adding additional query param in our request for us to identify which class is being requested to handle the request.

Maybe something like below:

public function index(ProductsDataTable $productDatatable, UsersDataTable $userDatatable)
{    
if (request()->has('product') {
    return $productDatatable->render('view');
}

if (request()->has('user') {
    return $productDatatable->render('view');
}

$user = Auth::user();

$products = $user->products;

return view('admin.dashboard', compact('products', 'user', 'productDatatable', 'userDatatable'));
}

Upvotes: 3

Related Questions