yajra / laravel-datatables-html

Laravel DataTables HTML Builder Plugin
https://yajrabox.com/docs/laravel-datatables/html-installation
MIT License
272 stars 61 forks source link

Ability to use static data (no server-side) #221

Open OzanKurt opened 3 months ago

OzanKurt commented 3 months ago

I recently wanted to use the package for a "array based datatable".

Sadly when I do;

{!! $dataTable->table() !!}

it doesn't generate the tables body.

I added some logic to the Builder class so that we can make it fill the tbody IF the serverSide option is disabled.

Here is an example DataTable I've prepared along with 2 methods makingRowExample and makingCellExample explaining how the Row and Cell classes apis work. I tried to make things similar to the Column class which we already.

There area a couple important places I've marked via comments inside the code.


<?php

namespace App\DataTables;

use App\DataTables\Core\Html\Column;
use App\Models\User;
use Yajra\DataTables\Html\Builder;
use Yajra\DataTables\Html\Cell;
use Yajra\DataTables\Html\Row;
use Yajra\DataTables\Services\DataTable;

class ExampleStaticDataTable extends DataTable
{
    // IMPORTANT: 
    // You can name this method whatever you want, it will simply allow you to populate the rows data
    public function buildRows()
    {
        $users = User::query()->get();

        $rows = [];

        /** @var User $user */
        foreach ($users as $user) {
            $rows[] = [
                'full_name' => $user->full_name,
                'email' => $user->email,
                'created_at' => $user->created_at?->format('Y-m-d H:i:s') ?? 'N/A',
            ];
        }

        return $rows;
    }

    // IMPORTANT: 
    // Here we call the `rows(array $rows = [])` method on the `Builder` instance
    // set the `serverSide` attribute to `false`
    public function html(): Builder
    {
        return $this
            ->builder()
            ->rows($this->buildRows())
            ->serverSide(false);
    }

    public function getColumns(): array
    {
        return [
            Column::make('full_name'),
            Column::make('email'),
            Column::make('created_at'),
        ];
    }

    // IMPORTANT: 
    // Example usages of the Row api
    public function makingRowExample()
    {
        // Option 1:
        //      If your row doesn't have any attributes,
        //      you can directly use array for its cells.
        $rowExample1 = [
            // Cells here...
        ];

        // Option 2:
        //      If your row has attributes,
        //      you must put the cells to the `cells` key.
        $rowExample2 = [
            'row-class' => 'gray-row',
            'cells' => [
                // Cells here...
            ],
        ];

        // Option 3:
        //      If your row has no attributes,
        //      leave the first parameter as an empty array.
        $rowExample3 = Row::make([
            'row-class' => 'gray-row',
        ], [
            // Cells here...
        ]);
        $rowExample4 = Row::make([
            'row-class' => 'gray-row',
        ])->cells([
            // Cells here...
        ]);
    }

    // IMPORTANT: 
    // Example usages of the Cell api
    public function makingCellExample()
    {
        // Option 1 - Directly inside Row array as `key => value` pairs
        $cellExample1_1 = [
            'column_1' => 'Column #1 Content',
            'column_2' => 'Column #2 Content',
        ];
        $cellExample1_2 = [
            'cells' => [
                'column_1' => 'Column #1 Content',
                'column_2' => 'Column #2 Content',
            ],
        ];

        // Option 2 - Using array
        $cellExample2 = [
            'column' => 'column_1',
            'content' => 'Column #1 Content',
        ];

        // Option 3 - Using Cell Object
        $cellExample3_1 = Cell::make('column_1', 'Column #1 Content');
        $cellExample3_2 = Cell::make('column_1')->content('Column #1 Content');
    }
}
OzanKurt commented 3 months ago

Hello @yajra ,

Could you please have a look at this and share me your feedback?

Here I also added the basic usage of the datatable for the controller and the blade parts.

class TestController extends Controller
{
    public function test()
    {
        $dataTable = new ExampleStaticDataTable();

        return view('test')->with([
            'dataTable' => $dataTable->html(),
        ]);
    }
}
{!! $dataTable->table() !!}
{!! $dataTable->scripts() !!}
1190 commented 3 months ago

hey @yajra, could you please review this?

yajra commented 3 months ago

@OzanKurt this is a great feature, thanks for sending the PR. I will test this as soon as I can.

One thing I noticed is that maybe we can simplify the syntax further by setting serverSide: false by default when rows are used.

    public function html(): Builder
    {
        return $this
            ->builder()
            ->rows($this->buildRows()) -- calling this will set serverSide to false
            ->serverSide(false); -- so we can remove this line
    }
sonarcloud[bot] commented 3 months ago

Quality Gate Passed Quality Gate passed

Issues
2 New issues
0 Accepted issues

Measures
0 Security Hotspots
0.0% Coverage on New Code
0.0% Duplication on New Code

See analysis details on SonarCloud

OzanKurt commented 3 months ago

Automatically calling serverSide(false) makes so much sense!

In addition to this I am currently working on the option to load the initial data from ajax while having serverSide(false).

I will send a new update in a couple days.

yajra commented 2 months ago

Thanks for the updates, let me know if this is ready for review again.