tttstudios / alpinejs-table

27 stars 7 forks source link

Cover.png

Alpinejs Table

Alpinejs Table is a Laravel package to inject a simple table view component into any Laravel project.

Built with Laravel, Alpine.js, Moment.js, @bevacqua/rome, and Tailwind CSS .

Main Features:

Jump to:



Dependencies

Recommended:

You can use this package in older versions of Laravel, but extra installation steps are required (as demonstrated below).



Installation

1. Via composer

composer require tttstudios/alpinejs-table

2. Manual Installation

For Laravel ≥ 5.7

1) Unzip the code and put it under your-repo/packages/tttstudios/ folder, so it looks like this:

├── your-repo
│   ├── app
│   ├── config
│   ├── composer.json
│   ├── vendor
│   └── packages
│      └── tttstudios
│          └── alpinejs-table

2) Add one line to your-repo/composer.json:

"autoload": {
    "psr-4": {
        "Tttstudios\\AlpinejsTable\\": "packages/tttstudios/alpinejs-table/src/"
    },
}

3) Then, add one line to your-repo/config/app.php:

'providers' => [
    Tttstudios\AlpinejsTable\Providers\AlpinejsTableServiceProvider::class
]

4) Lastly, refresh composer's autoload file by running:

composer dump-autoload

For Laravel < 5.7:

1) Copy all the source files under alpinejs-table/resources/views to your own repo's views/alpinejs-table folder.

2) Use Laravel Blade's @include() syntax to use them in view files. See examples below.



Basic Usage (Bundle)

Alpinejs Table is shipped with 3 Blade Aliases:

Blade Alias Description
AlpinejsTableBundle import a bundled javascript file with all its dependencies (including Alpine.js )
AlpinejsTableHtml import a blade view file
AlpinejsTableCss import all styles required by the table

For Laravel ≥ 5.7

You can use Alpinejs Table out of the box. Simply pass an array to AlpineHtml()'s collection in any blade view.

1) Format data into an array:

// ExampleController.php:

public function index() {

    $users=\App\User::get()->map(function ($user) {
        return [
            'status' => $user->status,
            'name'   => $user->name,
            'email'  => $user->email,
        ];
    })->all();

    return view('example', compact('users'));
}

2) Pass array to blade view:

<!-- in example.blade.php -->

<!--Import styles-->
<style> @AlpinejsTableCss() </style>

<!--Import js scripts-->
<script> @AlpinejsTableBundle() </script>

<!--Import table html-->
@AlpinejsTableHtml(['collection' => $users])

And this is what you get:

2020-06-17_16.58.57.gif

For Laravel < 5.7

Prerequisite: Copy all the files under alpinejs-table/resources/views to your own repo's views/alpinejs-table folder.

# in example.blade.php:

<style> @include('alpinejs-table.css') </style>

<script> @include('alpinejs-table.js-bundle') </script>

@include('alpinejs-table.html', ['collection' => $users])




Basic Usage (standalone)

If your app already has Alpine.js imported, then you don't need to import the bundled javascript file. Instead, you can call AlpineJsTableCore . Example:

# in example.blade.php:

<style> @AlpinejsTableCss() </style>

<!-- Without importing Alpine.js: -->
<script> @AlpinejsTableCore() </script>

@AlpinejsTableHtml(['collection' => $users])

For Laravel < 5.7

# in example.blade.php:

<style> @include('alpinejs-table.css') </style>

<!-- Without importing Alpine.js: -->
<script> @include('alpinejs-table.js-core') </script>

@include('alpinejs-table.html', ['collection' => $users])




Integration with your own js/css

You can tell that Alpinejs Table is using moment.js to parse date & time, and use Tailwind CSS to compose styles. If your app has imported them in global scope, or if you want to integrate Alpinejs Table's source code into your app's bundled js & css, simple follow these steps (Laravel ≥5.7 only):

1) Publish Alpinejs Table's assets by running:

php artisan vendor:publish --tag=alpinejs-table

2) The command above will copy these files into your repo:

# js:
/resources/js/plugins/rome-modified.js
/resources/js/plugins/alpinejs-table.js

# css:
/resources/sass/plugins/alpinejs-table.scss

3) Then you can import Alpinejs Table's core js into your own app.js :

// Source File: /resources/js/app.js

import 'alpinejs';

import AlpinejsTablePlugin from './plugins/alpinejs-table.js'

// Make it accessible in global ssope:
window.AlpinejsTablePlugin = AlpinejsTablePlugin;

4) And you can import Alpinejs Table's styles into your own app.scss :

/* Source File: /resources/sass/app.scss */

@tailwind base;

@tailwind components;

@import 'plugins/alpinejs-table';

@tailwind utilities;

5) Lastly, you only need to import AlpinejsTableHtml alone:

<!-- in example.blade.php -->

@AlpinejsTableHtml(['collection' => $users, 'options'=>$options])




Built-in Filters

1. Text Filter

Alpinejs Table generates a text filter for each column by default, which means, all columns can be filtered by text matching out of the box, unless you intentionally disable it.

2020-06-24_13.59.26.gif

2. Dropdown Filter

For limited data types, you may need a dropdown filter. For example: status may only have 2 valid values: Active or Pending . In this case, you can set it as a dropdown filter.

Example:

1) Format data into an array:

// ExampleController.php:

public function index() {

    $users=\App\User::get()->map(function ($user) {
        return [
            'status' => $user->status,
            'name'   => $user->name,
            'email'  => $user->email,
        ];
    })->all();

    $options=[
         'dropdowns' => ['status'],
    ];

    return view('example', compact('users', 'options'));
}

2) Pass array to blade view:

<!-- in example.blade.php -->

<style> @AlpinejsTableCss() </style>

<script> @AlpinejsTableBundle() </script>

@AlpinejsTableHtml(['collection' => $users, 'options' => $options])

And this is what you'll get:

Untitled.png

3. Date Filter

If some column is in date format. You may find it useful to define dates in options.

Example:

// ExampleController.php:

public function index() {

    $users=\App\User::get()->map(function ($user) {
        return [
            'status' => $user->status, // "Active" or "Pending"
            'name'   => $user->name,
            // must be in ISO 8601 format, e.g.: 2020-05-27T18:26:58+00:00
            'birthday'  => $user->birthday->toIso8601String()
        ];
    })->all();

    $options=[
        'dropdowns' => ['status'],
        'dates' => ['birthday'],
    ];

    return view('example', compact('users', 'options'));
}

Voila! The birthday column turns into a date picker automatically. Thank @bevacqua/rome for this great date picker plugin.

2020-06-16_18.37.29.gif

You can even set your own date format:

$options=[
    'dates' => ['birthday'],
    'dateFormat' => 'YYYY/M/D',
  ];

2020-06-17_15.25.34.gif



Customizations

1. Customize Cell Width

Alpinejs Table has a default cell width of 200px for each column. You may customize the width of each cell by passing a javascript closure to cellWidth(key)

Example:

$options=[
        // make sure the syntax is for Javascript:

        'cellWidth(key)'=>' 

        if(key=="status")
            return `120px`;

        if(key=="email")
            return `400px`;

        return `200px`;
    ',
];

Refresh the page and you can get the new layout:

Untitled%201.png

2. Customize Pagination

Alpinejs Table displays 10 entries per page by default. You can easily override it by setting perPage in options:

Example:

$options=[
    'perPage' => 24
];

You can also set the options to allow visitors on change perPage on the fly:

$options=[
    'perPageOptions' => [24, 48, 96]
];

Then You can see the settings in effect in bottom right of the table:

2020-06-16_18.54.55.gif



3. Customize Header Titles

By default, Alpinejs Table transforms key into title case and display in header. For example: user_email will be transformed into User Email.

In case you need to customize the title, you can use titleRenderer(key) :

Example:

// ExampleController.php:

    $options=[
        'titleRenderer(key)'=>'
            if(key=="id")
                return `User ID`;

            // by default: return nothing
        '
    ];

Result:

Untitled%202.png



4. Customize Cell Content

Sometimes you need to display a transformed content for some cells. For example, you may want to show red font color for users with "Pending" status, or even add different action buttons for different cells .

Here comes the magic of cellRenderer(key,cell,row) :

Example:

// ExampleController.php:

public function index() {

    $users=\App\User::get()->map(function ($user) {
        return [
            'id'     => $user->id,
            'status' => $user->status,
            'name'   => $user->name,
            'email'  => $user->email,
        ];
     })->all();

    $options=[
        'cellRenderer(key,cell,row)'=>'

            if(key == "status" && cell.value == "Pending")
                return `<span style="color:red">` + cell.value + `</span>`;

            if(key == "name")
            {
                const isPending = row.status.value == "Pending";
                return cell.value 
                        + `<a class="`+(isPending ? "btn-dark" : "btn-green") + ` float-right" href="https://github.com/tttstudios/alpinejs-table/blob/develop/users/` + row.id.value + `">`
                                + (isPending ? "Approve" : "Details")
                        +`</a> `;
            }

            return cell.value; // default
        '
    ];

    return view('example', compact('users', 'options'));
}

Result:

Untitled%203.png



Extra Options

1. notVisible:

The column will not be displayed, but its value can still be accessed by row in closures.

Example:

// ExampleController.php:

    $options=[
        'notVisible' => ['id']
        'cellRenderer(key,cell,row)'=>'
            if(key=="name")
                return `<b style="color:blue">ID #`
                        + row.id.value 
                        + "</b>: "
                        + cell.value;
            return cell.value;
        '
    ];

Result:

Untitled%204.png

2. notSortable:

The column can not be sorted, but its value can still be accessed by row in closures.

Example:

// ExampleController.php:

    $options=[
        'notSortable' => ['email']
    ];

Result:

Pasted_Image_2020-06-17__4_25_PM.png

3. notFilterable:

The column can not be filtered by text or dropdown, but its value can still be accessed by row in closures.

Example:

// ExampleController.php:

    $options=[
        'notFilterable' => ['email']
    ];

Result:

Pasted_Image_2020-06-17__4_29_PM.png



Appendix

Option Parameters

Parameter type Example Value Description
dropdowns array ['status'] Set dropdown filter to a column
dates array ['birthday'] Set date filter to a column
dateFormat string 'YYYY/M/D' Set date format to a date filter
perPage integer 24 Set "per page" for pagination
perPageOptions array [24, 48, 96] Set perPage options for pagination
notVisible array ['id', 'password'] Hide columns from showing in table
notSortable array ['email'] Hide sort button from columns
notFilterable array ['action'] Hide filter from columns
cellWidth(key) js closure 'return `200px`; ' Customize cell width for any column
titleRenderer(key) js closure 'if(key=="id") return `User ID`; ' Customize title width for column header
cellRenderer(key,cell,row) js closure 'return cell.value; ' Customize cell content




Notes

Alpinejs Table load all data into a single javascript instance. Performance can be compromised if there are too many data.



License

Alpinejs Table is open-sourced software licensed under the MIT license.



Contributors

@haoluo-ttt

@fpena




Premium Support By TTT Studios

Alpinjs Table is presented by the web developing team at TTT Studios. We are a Digital Innovation Studio based out of Vancouver, Canada, delivering custom software and solutions that are designed and developed 100% in-house. The technologies we work with include AR & VR, IoT, AI, security & encryption, and cloud computing.

ttt-logo.png