🪑

Laravel-AdminLTEのDatatablesのheads,configを管理しやすくする

2022/11/13に公開

はじめに

Laravel-AdminLTEのDataTablesコンポーネントでは、ヘッダセルは$heads、設定は$configにデータを格納してBladeコンポーネントへ渡します。
$heads,$configはライブラリのWikiではBladeの@phpディレクティブ内に記述されています。

hogehoge.blade.php
@php
//例
$heads = [
    'ID',
    'Name',
    ['label' => 'Phone', 'width' => 40],
    ['label' => 'Actions', 'no-export' => true, 'width' => 5],
];

...

$config = [
    'order' => [[1, 'asc']],
    'columns' => [null, null, null, ['orderable' => false]],
];
@endphp
...

これでは管理しにくいので、Blade外に出して管理しやすくなるようにしていきます。

環境

  • Windows11(WSL2)
  • PHP 8.0.x
  • Node.JS 16.16.x
  • Laravel 8.6.x
  • Composer 2.x
  • npm 8.11.x
  • Laravel-AdminLTE 3.8.4

Laravel-AdminLTEインストールまで

今回Laravel Sailは使いません

$ composer create-project laravel/laravel:^8 laravel-adminlte-datatables
$ cd laravel-adminlte-datatables

# Laravel Breezeインストール
$ composer require laravel/breeze:^2.1 --dev
$ php artisan breeze:install
# Breeze scaffolding installed successfully.
# Please execute the "npm install && npm run dev" command to build your assets.
$ npm install && npm npm run dev

# Laravel-AdminLTEインストール
$ composer require jeroennoten/laravel-adminlte
$ php artisan adminlte:install

Controller作成、ルーティング追加、View作成まで

Controller作成

$ php artisan make:controller DataTablesShowController --invokable
app/Http/Controllers/DataTablesShowController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class DataTablesShowController extends Controller
{
    /**
     * Handle the incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function __invoke(Request $request)
    {
        $data = [
            [22, 'John Bender', '+02 (123) 123456789'], 
            [19, 'Sophia Clemens', '+99 (987) 987654321'], 
            [3, 'Peter Sousa', '+69 (555) 12367345243']
        ];
        return view('datatables',compact(
            'data',
        ));
    }
}

ルーティング追加

routes/web.php
Route::get('/', function () {
    return view('welcome');
});

Route::middleware(['auth'])->group(function () {
    Route::get('/dashboard', function () {
        return view('dashboard');
    })->name('dashboard');

+    Route::get('/datatables', DataTablesShowController::class);
});

require __DIR__.'/auth.php';

View作成

Laravel-AdminLTEのWikiを参照しながら記述していきます。
一旦表示確認のため、Wikiのサンプルコード通り@phpディレクティブに$heads,$configを記述します。

resources/views/datatables.blade.php
@extends('adminlte::page')

@section('title', 'Datatables')

@section('content_header')
    <h1>Datatables</h1>
@stop

@php
    $heads = [
        'ID', 
        'Name', 
        [
            'label' => 'Phone',
             'width' => 40
        ]
    ];
    
    $config = [
        'order' => [
            [1, 'asc']
        ],
    ];
@endphp

@section('content')
    <x-adminlte-datatable id="table1" :heads="$heads">
        @foreach ($data as $row)
            <tr>
                @foreach ($row as $cell)
                    <td>{!! $cell !!}</td>
                @endforeach
            </tr>
        @endforeach
    </x-adminlte-datatable>
@stop

@section('css')
@stop

@section('js')
@stop

Datatablesプラグインを有効化します。

config/adminlte.php
...

    'plugins' => [
        'Datatables' => [
            'active' => true, //有効化
            'files' => [
...

以下のような表示になります。

$heads,$configの移動

GitHubでLaravel-AdminLTEを利用しているリポジトリを検索すると、$heads,$configはBladeもしくはControllerに書かれているのがほとんどでした。

Controllerに直書きするのも微妙なので、config/adminlte.phpファイルに書くことにしました。

config/adminlte.php
...
    'datatables' => [
        'hoge' => [
            'heads' => [
                'ID',
                'Name',
                [
                    'label' => 'Phone',
                    'width' => 40,
                ],
            ],
            'config' => [
                'order' => [
                    [1, 'asc'],
                ],
            ],
        ],
    ],
...

DataTablesを使うページが増えても対応できるようにhogeで括っておきます。

Controllerでconfigの値を取得します。

app/Http/DataTablesShowController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class DataTablesShowController extends Controller
{
    /**
     * Handle the incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function __invoke(Request $request)
    {
        $data = [
            [22, 'John Bender', '+02 (123) 123456789'], 
            [19, 'Sophia Clemens', '+99 (987) 987654321'], 
            [3, 'Peter Sousa', '+69 (555) 12367345243']
        ];

+        $dataTableHeads = config('adminlte.datatables.hoge.heads');
+        $dataTableConfig = config('adminlte.datatables.hoge.config');

        return view('datatables',compact(
            'data',
+            'dataTableHeads',
+            'dataTableConfig',
        ));
    }
}

Viewも合わせて変更します。

resources/views/datatables.blade.php
@extends('adminlte::page')

@section('title', 'Datatables')

@section('content_header')
    <h1>Datatables</h1>
@stop

-@php
-    $heads = [
-        'ID', 
-        'Name', 
-        [
-            'label' => 'Phone',
-             'width' => 40
-        ]
-    ];
-    
-    $config = [
-        'order' => [
-            [1, 'asc']
-        ],
-    ];
-@endphp

@section('content')
-    <x-adminlte-datatable id="table1" :heads="$heads">
+    <x-adminlte-datatable id="table1" :heads="$dataTableHeads" :config="$dataTableConfig">
        @foreach ($data as $row)
            <tr>
                @foreach ($row as $cell)
                    <td>{!! $cell !!}</td>
                @endforeach
            </tr>
        @endforeach
    </x-adminlte-datatable>
@stop

@section('css')
@stop

@section('js')
@stop

これで完了です。

DataTablesを日本語化したい場合

config内languageプロパティの値で指定する必要がある。
どのページでも値は同じになるので、database.blade.phpに直接記述する。

languageとconfigを結合してあげる必要があることに注意

resources/views/vendor/adminlte/components/tool/datatable.blade.php
{{-- Table --}}

 <div class="table-responsive">

 <table id="{{ $id }}" style="width:100%" {{ $attributes->merge(['class' => $makeTableClass()]) }}>

    {{-- Table head --}}
    <thead @isset($headTheme) class="thead-{{ $headTheme }}" @endisset>
        <tr>
            @foreach($heads as $th)
                <th @isset($th['width']) style="width:{{ $th['width'] }}%" @endisset
                    @isset($th['no-export']) dt-no-export @endisset>
                    {{ is_array($th) ? ($th['label'] ?? '') : $th }}
                </th>
            @endforeach
        </tr>
    </thead>

    {{-- Table body --}}
    <tbody>{{ $slot }}</tbody>

    {{-- Table footer --}}
    @isset($withFooter)
        <tfoot @isset($footerTheme) class="thead-{{ $footerTheme }}" @endisset>
            <tr>
                @foreach($heads as $th)
                    <th>{{ is_array($th) ? ($th['label'] ?? '') : $th }}</th>
                @endforeach
            </tr>
        </tfoot>
    @endisset

 </table>

 </div>

+@php
+    $languages = [
+        'language' => [
+           'url' => '//cdn.datatables.net/plug-ins/1.13.1/i18n/ja.json',
+        ],
+    ];
+@endphp

{{-- Add plugin initialization and configuration code --}}
@push('js')
 <script>
    
    $(() => {
-        $('#{{ $id }}').DataTable( @json($config)) );
+        $('#{{ $id }}').DataTable( Object.assign(@json($config),@json($languages)) );

    })

 </script>
@endpush

{{-- Add CSS styling --}}

@isset($beautify)
    @push('css')
    <style type="text/css">
        #{{ $id }} tr td,  #{{ $id }} tr th {
            vertical-align: middle;
            text-align: center;
        }
    </style>
    @endpush
@endisset

さいごに

今回のやり方が最適解かは分からないですが、BladeやControllerに直で書くよりかは可読性が高くなったかと思います。

最近はLaravel-AdminLTEをよく触るので、また他の記事を書きます。

Discussion