Git Product home page Git Product logo

laravel-table's Introduction

Package looking for co-maintainers

I've been quite busy professionally lately and I'm currently looking for one or more co-maintainers to help me to maintain and develop this package.

Current roadmap:

  • PR reviewing
  • Livewire 3 compatibility
  • Tailwind 3 compatibility

Please contact me at arthur[dot]lorent[at]gmail.com to apply.


Laravel Table

Latest Stable Version Total Downloads Build Status Coverage Status License: MIT

Generate tables from Eloquent models

Save time and easily render tables in your views from Eloquent models.

Tables can be generated under the following UI frameworks:

  • Bootstrap 5
  • Bootstrap 4
  • TailwindCSS 3 (upcoming feature)

Found this package helpful? Please consider supporting my work!

Donate Donate

Compatibility

Laravel version Livewire version PHP version Package version
^9.0 | ^10.0 ^2.0 8.1.* | 8.2.* ^5.3
^8.0 | ^9.0 ^2.0 ^8.1 ^5.0
^7.0 | ^8.0 X ^7.4 | ^8.0 ^4.0
^7.0 | ^8.0 X ^7.4 | ^8.0 ^3.0
^6.0 | ^7.0 X ^7.4 | ^8.0 ^2.0
^5.8 | ^6.0 | ^7.0 X ^7.2 | ^7.3 | ^7.4 ^1.3
^5.5 | ^5.6 | ^5.7 | ^5.8 | ^6.0 X ^5.8 | ^7.1 ^1.0

Upgrade guide

Usage

Create your table with the following command:

php artisan make:table UsersTable --model=App/Models/User

Configure your table in the UsersTable generated class, which can be found in the app\Tables directory:

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Column;
use Okipe\LaravelTable\Formatters\Date;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }

    protected function columns(): array
    {
        return [
            Column::make('id')->sortable(),
            Column::make('name')->searchable()->sortable(),
            Column::make('email')->searchable()->sortable(),
            Column::make('created_at')
                ->format(new DateFormatter('d/m/Y H:i', 'Europe/Paris'))
                ->sortable(),
            Column::make('updated_at')
                ->format(new DateFormatter('d/m/Y H:i', 'Europe/Paris'))
                ->sortable()
                ->sortByDefault('desc'),
        ];
    }
}

And display it in a view:

<livewire:table :config="App\Tables\UsersTable::class"/>

Table of contents

Installation

  • Install the package with composer:
composer require okipa/laravel-table

This package uses Livewire under the hood and its installation is required.

You'll have to follow the installation instructions if Livewire is not already installed on your project.

Configuration

Optionally publish the package configuration:

php artisan vendor:publish --tag=laravel-table:config

Templates

Optionally publish the package templates:

php artisan vendor:publish --tag=laravel-table:views

Translations

All words and sentences used in this package are translatable.

See how to translate them on the Laravel official documentation: https://laravel.com/docs/localization#using-translation-strings-as-keys.

Here is the list of the words and sentences available for translation:

Status

  • Loading in progress...
  • No results were found.
  • You can rearrange the order of the items in this list using a drag and drop action.
  • Reset filters
  • Yes
  • No
  • Search by:
  • Reset research
  • Number of rows per page
  • Sort ascending
  • Sort descending
  • Actions
  • Bulk Actions
  • Create
  • Add
  • Show
  • Edit
  • Destroy
  • Activate
  • Deactivate
  • Verify Email
  • Unverify Email
  • Toggle On
  • Toggle Off
  • Are you sure you want to execute the action :action on the line #:primary?
  • Are you sure you want to execute the action :action on the field :attribute from the line #:primary?
  • Are you sure you want to execute the action :action on the :count selected lines?
  • The line #:primary does not allow the action :action and will not be affected.
  • :count selected lines do not allow the action :action and will not be affected.
  • The action :action has been executed on the line #:primary.
  • The action :action has been executed on the field :attribute from the line #:primary.
  • The action :action has been executed on the :count selected lines.
  • The line #:primary does not allow the action :action and was not affected.
  • :count selected lines do not allow the action :action and were not affected.
  • The list has been reordered.
  • Showing results <b>:start</b> to <b>:stop</b> on <b>:total</b>

How to

Create table configurations

Generate a table configuration by executing this command : php artisan make:table UsersTable.

If you want to generate a configuration with a predefined model, just add this option at the end: --model=App/Models/User.

You'll find all your generated table configurations in the app/Tables directory.

Display tables in views

Just call this Livewire component in your view with your configuration class name passed in the config parameter.

<livewire:table :config="App\Tables\UsersTable::class"/>

Pass external data to your tables

In case you have specific attributes to transmit to your table configuration, you should pass them to the configParams parameter.

This could be useful when you have to transmit external information to your table.

<livewire:table :config="App\Tables\UsersTable::class" :configParams="['categoryId' => 1]"/>

You should then declare the passed attributes as public attributes your table configuration.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    // You will now be able to use the provided `$this->categoryId` category ID in your table configuration.
    public int $categoryId;

    // ...
}

Generate tables from Eloquent models

To generate a table from an Eloquent model, you'll just have to call the model method on your table.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
}

Override native selects behaviour on your tables

You may want to override native HTML select components behaviour on your tables.

You will be able to add a data attribute (which is known as the best practice to add extra features to a HTML component) to all the HTML select components displayed on your tables by defining an array of HTML attribute as value for the laravel-table.html_select_components_attributes config key.

// `data-selector` HTML attribute will be appended to all tables HTML select components.
'html_select_components_attributes' => ['data-selector' => true],

Add query instructions on tables

To add specific query instructions on tables, use the available query method.

You'll be able to set specific Eloquent instructions by passing a closure parameter to the query method on your table.

This closure will allow you to manipulate a \Illuminate\Database\Eloquent\Builder $query argument.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Illuminate\Database\Eloquent\Builder;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            ->query(fn(Builder $query) => $query->where('category_id', 1));
    }   
}

Handle tables number of rows per page, pagination and navigation status

You have two ways to allow or disallow users to choose the number of rows that will be displayed per page:

  • Activate or deactivate it globally from the laravel-table.enable_number_of_rows_per_page_choice config boolean value
  • Override global activation status by executing the enableNumberOfRowsPerPageChoice() method on your table
namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            ->enableNumberOfRowsPerPageChoice(false);
    }
}

Following the same logic, you'll be able to define the number of rows per page options that will be available for selection:

  • Set options globally from the laravel-table.number_of_rows_per_page_default_options config array value
  • Override global options by executing the numberOfRowsPerPageOptions() method on your table

The first available option will be automatically selected and applied on table initialization.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            // Table will display 5 rows on initialization and will allow displaying 10, 15, 20 or 25 rows.
            ->numberOfRowsPerPageOptions([5, 10, 15, 20, 25]);
    }
}

Pagination will automatically be handled, according to the number of rows to display and the total number of rows, as well as a navigation status.

Both of them will be displayed in the table footer.

Set conditional row class

Define conditional row class on tables by passing a closure argument to the rowClass method.

This closure will allow you to manipulate a Illuminate\Database\Eloquent $model argument and has to return an array of classes where the array key contains the class or classes you wish to add, while the value is a boolean expression.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            ->rowClass(fn(User $user) => [
                'table-danger' => ! $user->active,
            ]);
    }
}

Setup table filters

Configuring table filters will make them appear as select HTML components on a dedicated bar above the table.

The filters bar will not appear if no filter is declared.

This package provides the following built-in filters:

  • ValueFilter:
    • Requires string $label, string $attribute, array $options and bool $multiple = true arguments on instantiation
    • Filters the table based on whether the value of the selected options (or single option if multiple mode is disabled) is found in the given attribute
  • RelationshipFilter:
    • Requires string $label, string $relationship, array $options and bool $multiple = true arguments on instantiation
    • Filters the table based on whether the value of the selected options (or single option if multiple mode is disabled) is found in the given relationship
  • NullFilter
    • Requires a string $attribute argument on instantiation
    • Filters the table based on whether the value of the given attribute is null or not
  • BooleanFilter
    • Requires string $label and string $attribute arguments on instantiation
    • Filters the table based on whether the value of the given attribute is true or false

To use them, you'll have to pass an array to the filters method, containing the filter instances to declare.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Filters\NullFilter;
use Okipa\LaravelTable\Filters\ValueFilter;
use Okipa\LaravelTable\Filters\BooleanFilter;
use Okipa\LaravelTable\Filters\RelationshipFilter;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            ->filters([
                new ValueFilter('Email', 'email', User::pluck('email', 'email')->toArray()),
                new RelationshipFilter('Categories', 'categories', UserCategory::pluck('name', 'id')->toArray()),
                new NullFilter('Email Verified', 'email_verified_at'),
                new BooleanFilter('Active', 'active'),
            ]);
    }
}

You may need to create your own filters. To do so, execute the following command: php artisan make:table:filter MyNewFilter.

You'll find your generated table filter in the app/Tables/Filters directory.

You will now be able to use your new filter in your tables.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use App\Tables\Filters\MyNewFilter;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            ->filters([
                new MyNewFilter(),
            ]);
    }
}

Define table head action

Configure a table action that will be displayed as a button positioned at the right of the table head.

If no head action is declared, the dedicated slot for it in the table head will remain empty.

This package provides the following built-in head actions:

  • RedirectHeadAction:
    • Requires string $url, string $label, string $icon, array $class = ['btn', 'btn-success'] and bool $openInNewWindow = false arguments on instantiation
    • Redirects to the given URL from a click on the button
  • CreateHeadAction:
    • Requires string $createUrl and bool $openInNewWindow = false arguments on instantiation
    • Instantiate a pre-configured RedirectHeadAction with $createUrl as URL, __('Create') as label and config('laravel-table.icon.create') as icon

To use one of them, you'll have to pass an instance of it to the headAction method.

You'll be able to chain the following method to your head action:

  • when(bool $condition): Okipa\LaravelTable\Abstracts\AbstractHeadAction
    • Determines whether the head action should be enabled
namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\HeadActions\AddHeadAction;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            // Create head action will not be available when authenticated user is not allowed to create users
            ->headAction((new AddHeadAction(route('user.create')))->when(Auth::user()->cannot('create_users')));
    }
}

You may need to create your own head actions. To do so, execute the following command: php artisan make:table:head:action MyNewHeadAction.

You'll find your generated table head action in the app/Tables/HeadActions directory.

You will now be able to use your new head action in your tables.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use App\Tables\HeadActions\MyNewHeadAction;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            ->headAction(new MyNewHeadAction());
    }
}

Define table bulk actions

Configure table bulk actions that will be available in a dropdown positioned at the left of the table head.

If no bulk action is declared on your table, the dedicated column will not be displayed.

Important note: you'll have to set up a few lines of javascript to allow bulk actions confirmation requests and feedback to be working properly.

This package provides the built-in following bulk actions:

  • VerifyEmailBulkAction:
    • Requires a string $attribute argument on instantiation
    • Update the given attribute with the current datetime for all selected lines
  • CancelEmailVerificationBulkAction:
    • Requires a string $attribute argument on instantiation
    • Update the given attribute to null for all selected lines
  • ActivateBulkAction:
    • Requires a string $attribute argument on instantiation
    • Update the given attribute to true for all selected lines
  • DeactivateBulkAction:
    • Requires a string $attribute argument on instantiation
    • Update the given attribute to false for all selected lines
  • DestroyBulkAction:
    • Destroys all the selected lines

To use them, you'll have to pass a closure parameter to the bulkActions method. This closure will allow you to manipulate a Illuminate\Database\Eloquent $model argument and has to return an array containing bulk action instances.

You'll be able to chain the following methods to your bulk actions:

  • when(bool $condition): Okipa\LaravelTable\Abstracts\AbstractBulkAction
    • Determines whether the bulk action should be enabled on the table rows
  • confirmationQuestion(string|false $confirmationQuestion): Okipa\LaravelTable\Abstracts\AbstractBulkAction
    • Overrides the default action confirmation message
  • feedbackMessage(string|false $feedbackMessage): Okipa\LaravelTable\Abstracts\AbstractBulkAction:
    • Overrides the default action feedback message
namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\BulkActions\DestroyBulkAction;
use Okipa\LaravelTable\BulkActions\ActivateBulkAction;
use Okipa\LaravelTable\BulkActions\DeactivateBulkAction;
use Okipa\LaravelTable\BulkActions\VerifyEmailBulkAction;
use Okipa\LaravelTable\BulkActions\CancelEmailVerificationBulkAction;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            ->bulkActions(fn(User $user) => [
                new VerifyEmailBulkAction('email_verified_at'),
                new CancelEmailVerificationBulkAction('email_verified_at'),
                new ActivateBulkAction('active'),
                new DeactivateBulkAction('active'),
                (new DestroyBulkAction())
                    // Destroy action will not be available for authenticated user
                    ->when(Auth::user()->isNot($user))
                    // Override the action default confirmation question
                    // Or set `false` if you do not want to require any confirmation for this action
                    ->confirmationQuestion('Are you sure you want to delete selected users ?')
                    // Override the action default feedback message
                    // Or set `false` if you do not want to trigger any feedback message for this action
                    ->feedbackMessage('Selected users have been deleted.'),
            ]);
    }
}

You may need to create your own bulk actions. To do so, execute the following command: php artisan make:table:bulk:action MyNewBulkAction.

You'll find your generated table bulk actions in the app/Tables/BulkActions directory.

You will now be able to use your new bulk action in your tables.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use App\Tables\BulkActions\MyNewBulkAction;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            ->bulkActions(fn(User $user) => [
                new MyNewBulkAction(),
            ]);
    }
}

Define table row actions

Configure row actions on your table that will be displayed at the end of each row.

If no row action is declared on your table, the dedicated Actions column at the right of the table will not be displayed.

Important note: you'll have to set up a few lines of javascript to allow row actions confirmation requests and feedback to be working properly.

This package provides the built-in following row actions:

  • RedirectRowAction:
    • Requires string $url, string $title, string $icon, array $class = ['link-info'], string|null $defaultConfirmationQuestion = null, string|null $defaultFeedbackMessage = null and bool $openInNewWindow = false arguments on instantiation
    • Redirects to the given URL from a click on the link
  • ShowRowAction:
    • Requires string $showUrl and bool $openInNewWindow = false arguments on instantiation
    • Instantiate a pre-configured RedirectRowAction with $showUrl as URL, __('Show') as label and config('laravel-table.icon.show') as icon
  • EditRowAction:
    • Requires a string $editUrl argument on instantiation
    • Redirects to the model edit page on click
  • DestroyRowAction:
    • Destroys the line after being asked to confirm

To use them, you'll have to pass a closure parameter to the rowActions method. This closure will allow you to manipulate a Illuminate\Database\Eloquent $model argument and has to return an array containing row action instances.

You'll be able to chain the same methods as for a bulk action => See bulk actions configuration.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\RowActions\EditRowAction;
use Okipa\LaravelTable\RowActions\ShowRowAction;
use Okipa\LaravelTable\RowActions\DestroyRowAction;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            ->rowActions(fn(User $user) => [
                new ShowRowAction(route('user.show', $user)),
                new EditRowAction(route('user.edit', $user)),
                (new DestroyRowAction())
                    // Destroy action will not be available for authenticated user
                    ->when(Auth::user()->isNot($user))
                    // Override the action default confirmation question
                    // Or set `false` if you do not want to require any confirmation for this action
                    ->confirmationQuestion('Are you sure you want to delete user ' . $user->name . '?')
                    // Override the action default feedback message
                    // Or set `false` if you do not want to trigger any feedback message for this action
                    ->feedbackMessage('User ' . $user->name . ' has been deleted.'),
            ]);
    }
}

You may need to create your own row actions. To do so, execute the following command: php artisan make:table:row:action MyNewRowAction.

You'll find your generated table row actions in the app/Tables/RowActions directory.

You will now be able to use your new row action in your tables.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use App\Tables\RowActions\MyNewRowAction;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            ->rowActions(fn(User $user) => [
                new MyNewRowAction(),
            ]);
    }
}

You may need your row actions to be confirmed before they'll be executed and to trigger feedback messages.

You'll have to configure them in the same way you did for bulk actions.

Declare columns on tables

Declare columns on tables with the columns method available in your generated table configuration, from which you'll have to return an array of column instances.

To declare columns, just use the static make method that will await a string $attribute argument. This attribute will be used to get the default cell value.

By default, the column title will be defined to __('validation.attributes.<attribute>') in order to reuse attributes translations.

If you need to, you may use the title method that will await a string $title argument to set a specific column title that will override the default one.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Column;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
    
    protected function columns(): array
    {
        return [
            // Column attribute set to `id`, column value set from `$user->id` and colum title set to `__('validation.attributes.id')`
            Column::make('id'),
            // Column attribute set to `name`, value set from `$user->name` and column title set to `Username`
            Column::make('name')->title('Username'),
        ];
    }
}

Format column values

You'll sometimes need to apply specific formatting for your columns. There are a few ways to achieve this.

For specific cases, you should pass a closure parameter to the format method on your column.

This closure will allow you to manipulate a Illuminate\Database\Eloquent $model argument.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Column;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
    
    protected function columns(): array
    {
        return [
            // Value set from `$user->id`
            Column::make('id'),
            // Value set from closure
            Column::make('username')
                ->format(fn(User $user) => '<b> ' . $user->companies->implode('name', ', ') . '</b>'),
        ];
    }
}

If you want to apply the same formatting treatment repeatedly, you should create a formatter with the following command: php artisan make:table:formatter NewFormatter.

You'll find the generated formatter in the app\Table\Formatters directory.

You'll be able to reuse this formatter in your tables.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Column;
use App\Tables\Formatters\NewFormatter;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
    
    protected function columns(): array
    {
        return [
            Column::make('id'),
            Column::make('name')->format(new NewFormatter()),
        ];
    }
}

This package provides the following built-in formatters :

  • BooleanFormatter:
    • Displays the config('laravel-table.icon.active') active icon or the config('laravel-table.icon.inactive') inactive icon from a boolean value
  • DateFormatter:
    • Requires string $format and string $timezone arguments on instantiation
    • Displays a formatted string from a date or datetime value
  • StrLimitFormatter:
    • Allows optional int $limit and string $end arguments on instantiation
    • Displays a truncated string with a title allowing to see the full string on hover

Define column actions

Configure column actions on your table that will be displayed on their own cells.

Column actions have a lot in common with row actions.

Important note: you'll have to set up a few lines of javascript to allow column actions confirmation requests and feedback to be working properly.

This package provides the built-in following actions:

  • ToggleBooleanColumnAction:
    • Toggles the email verification status
  • ToggleBooleanColumnAction:
    • Toggles a boolean value

To use them, you'll have to pass a closure parameter to the action method. This closure will allow you to manipulate a Illuminate\Database\Eloquent $model argument and has to return an AbstractColumnAction instance.

You'll be able to chain the same methods as for a bulk action => See bulk actions configuration.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\ColumnActions\ToggleBooleanColumnAction;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;
use Okipa\LaravelTable\ColumnActions\ToggleBooleanColumnAction;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
    
    protected function columns(): array
    {
        return [
            Column::make('id'),
            Column::make('email_verified_at')
                // ToggleBooleanColumnAction action will not trigger any feedback message
                ->action(fn(User $user) => (new ToggleBooleanColumnAction()->feedbackMessage(false))
            Column::make('active')
                // ToggleBooleanColumnAction action will not be available for authenticated user
                ->action(fn(User $user) => (new ToggleBooleanColumnAction())->when(Auth::user()->isNot($user))),
        ];
    }
}

You may need to create your own column actions. To do so, execute the following command: php artisan make:table:column:action MyNewColumnAction.

You'll find your generated table column actions in the app/Tables/ColumnActions directory.

You will now be able to use your new column action in your tables.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use App\Tables\ColumnActions\MyNewColumnAction;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }

    protected function columns(): array
    {
        return [
            Column::make('id'),
            Column::make('action')->action(fn() => new MyNewColumnAction()),
        ];
    }
}

You may need your column actions to be confirmed before they'll be executed and to trigger feedback messages.

You'll have to configure them in the same way you did for bulk actions.

Configure columns searching

Allow searching on columns by calling the searching method.

When searchable fields are set, a search input will appear in the table head.

Searchable column titles will be used to indicate which field can be searched on the search input placeholder.

By default, searching will be applied to columns defined keys.

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
    
    protected function columns(): array
    {
        return [
            // Column will not be searchable
            Column::make('id'),
            // Table will be searchable from `$user->name`
            Column::make('name')->searchable(),
        ];
    }
}

You will be able to set up a custom searching behaviour by passing a closure to the searchable method.

This closure will be executed when searching will be triggered on the table and will allow you to manipulate a Illuminate\Database\Eloquent\Builder $query argument.

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
    
    protected function columns(): array
    {
        return [
            // Column will not be searchable
            Column::make('id'),
            // Column will be searchable using this closure
            Column::make('owned_companies')
                // ... Your custom formatting here
                ->searchable(fn(Builder $query, string $searchBy) => $query->whereRelation(
                    'companies',
                    'name',
                    'LIKE',
                    '%' . $searchBy . '%'
                ),
        ];
    }
}

Configure columns sorting

Allow sorting on columns by calling the sortable method.

Sortable columns will display clickable sort icons before their titles that will trigger ascending or descending sorting.

By default, sorting will be applied to columns defined keys.

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
    
    protected function columns(): array
    {
        return [
            // Column will not be sortable
            Column::make('id'),
            // Column will be sortable from `$user->name`
            Column::make('name')->sortable(),
        ];
    }
}

To sort a column by default, use the sortByDefault column method, which will allow you to pass a string $direction argument.

You can sort by default a column that is not sortable.

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
    
    protected function columns(): array
    {
        return [
            // Column will not be sortable
            Column::make('id'),
            // Column will be sorted descending by default on `$user->name`
            Column::make('name')->sortByDefault('desc'),
        ];
    }
}

You will be able to set up a custom sorting behaviour by passing a closure to the sortable method.

This closure will be executed when sorting will be triggered on the column and will allow you to manipulate a Illuminate\Database\Eloquent\Builder $query and a string $sortDir arguments (asc or desc).

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
    
    protected function columns(): array
    {
        return [
            // Column will not be sortable
            Column::make('id'),
            // Column will be sortable from this closure
            Column::make('companies_count') 
                // Custom formatting...
                ->sortable(fn(Builder $query, string $sortDir) => $query
                    ->withCount('companies')
                    ->orderBy('companies_count', $sortDir)),
        ];
    }
}

Allow columns to be reordered from drag and drop action

Allow columns to be reordered from drag and drop action by calling the reorderable method on your table.

This method will await a first string $attribute argument, an optional second string $title argument, and an optional third string $sortDirByDefault argument (accepting asc or desc values).

Important notes:

Activating this feature will:

  • Prepend a new column that will display the drag-and-drop icon defined in the laravel-table.icon.drag_drop config value, followed by the defined model order attribute value
  • Sort the rows from the defined model order attribute (asc by default)
  • Disable all other columns sorting as it is not compatible with drag-and-drop reordering
  • And of course, enable the drag-and-drop columns reordering by adding all the Livewire Sortable Plugin necessary markup
namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            // A new column will display the drag-and-drop icon, followed by the `position` attribute value
            // Rows will be sorted from the `position` model attribute and all other columns sorting will be disable
            ->reorderable('position');
    }
}

Tip: if you are using packages like spatie/eloquent-sortable to handle your Eloquent models sorting behaviour with a grouping query, you'll have to also set this grouping query in the table query instruction.

Declare results on tables

To display results, you'll have to return an array of result instances from the results method available in your generated table configuration.

If no result is declared, their dedicated space will remain empty.

Results should be declared this way:

  1. Create a Result instance with the static make method
  2. Chain the title method that will await a string $title argument
  3. Chain the format method that will await a closure, letting you manipulate Illuminate\Database\Query\Builder $totalRowsQuery and Illuminate\Support\Collection $displayedRowsCollection params
namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Column;
use Okipa\LaravelTable\Result;
use Illuminate\Support\Collection;
use Illuminate\Database\Query\Builder;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(User::class);
    }
    
    protected function columns(): array
    {
        return [
            Column::make('id'),
        ];
    }
    
    protected function results(): array
    {
        return [
            // This result uses the first $totalRowsQuery closure param to compute its value.
            // In this example, all users contained in database with unverified email will be count.
            Result::make()
                ->title('Total of users with unverified email')
                ->format(static fn(Builder $totalRowsQuery) => $totalRowsQuery
                    ->whereNull('email_verified_at')
                    ->count()),
            // This result uses the second $displayedRowsCollection closure param to compute its value.
            // In this example, all displayed inactive users will be count.
            Result::make()
                ->title('Displayed inactive users')
                ->format(static fn(
                    Builder $totalRowsQuery,
                    Collection $displayedRowsCollection
                ) => $displayedRowsCollection->where('active', false)->count()),
        ];
    }
}

Set up a few lines of JavaScript

You'll have to add few Javascript lines to your project once this package is installed, in order to allow confirmation requests and actions feedback to be working properly.

When an action is requesting the user confirmation, it will not be directly executed. A table:action:confirm Livewire event will be emitted instead with the following parameters:

  1. The action type
  2. The action identifier
  3. The model primary key related to your action
  4. The $confirmationQuestion attribute from your action

As you will see on the provided snippet below, the 4th param of this event is the only one you'll have to use in order to request the user confirmation. The 3 first params are only there to be sent back to a new event when the action is confirmed by the user. Just ignore them in your treatment.

You will have to intercept this event from your own JS script and prompt a confirmation request.

When the action is confirmed by the user, you'll have to emit a new laraveltable:action:confirmed Livewire event that will trigger the action execution. You'll have to pass it the 3 first arguments provided in the table:action:confirm event:

  1. The action type
  2. The action identifier
  3. The model primary key related to your action

Here is an JS snippet to show you how to proceed:

// Listen to the action confirmation request
Livewire.on('laraveltable:action:confirm', (actionType, actionIdentifier, modelPrimary, confirmationQuestion) => {
    // You can replace this native JS confirm dialog by your favorite modal/alert/toast library implementation. Or keep it this way!
    if (window.confirm(confirmationQuestion)) {
        // As explained above, just send back the 3 first argument from the `table:action:confirm` event when the action is confirmed
        Livewire.emit('laraveltable:action:confirmed', actionType, actionIdentifier, modelPrimary);
    }
});

Once an action is executed, a table:action:feedback Livewire event is triggered (it sometimes depends on the configuration of a feedback message).

Following the same logic, you'll have to intercept it from a JS script as shown on the snippet below to provide an immediate feedback to the user:

Livewire.on('laraveltable:action:feedback', (feedbackMessage) => {
    // Replace this native JS alert by your favorite modal/alert/toast library implementation. Or keep it this way!
    window.alert(feedbackMessage);
});

Finally, in order to allow head RedirectHeadAction and CreateHeadAction to open link in new tab, you'll also have to add the following JS snippet:

Livewire.on('laraveltable:link:open:newtab', (url) => {
    window.open(url, '_blank').focus();
});

Trigger Livewire events on table load

You may want to trigger some events on table load, in order to load UI third party JS libraries for example.

You can do it using the table emitEventsOnLoad method, that will await an array of events.

namespace App\Tables;

use App\Models\User;
use Okipa\LaravelTable\Table;
use Illuminate\Database\Eloquent\Builder;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;

class UsersTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()
            ->model(User::class)
            // This event will be loaded each time your table will be rendered
            // in order to keep your UI third party libraries rendering,
            // even when its HTML is refreshed.
            ->emitEventsOnLoad(['js:selector:init' => ['some', 'params']]);
    }   
}

Interact with your tables from events

You will be able to interact with your tables by sending them the following Livewire events:

  • laraveltable:refresh
    • Allows optional array $configParams = [], and array $targetedConfigs = [] arguments
    • Refreshes your tables and (optionaly) set external table config data with (optional) table targeting to only refresh specific ones (empty $targetedConfigs array will refresh all tables one page)

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Credits

License

The MIT License (MIT). Please see License File for more information.

laravel-table's People

Contributors

costeirs avatar iaotle avatar mostafasoufi avatar okipa avatar szepeviktor avatar tmigue avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravel-table's Issues

Add ->prepend() + ->append() method

Implement ->prepend() and ->append() methods to add html code before or after the generated line value.
Give the possibility to display the prepended or appended html even if there is no value (by default, do not display them if no value is detected).

locale pt-BR don't work

I copied the file laravel-table.php to the locale pt-BR/ but it only appears in English, it does not translate the texts.

Display only certain rows depending on value

Hello!

I don't know if this is possible in the current version, but it would be nice if we could only display certain rows of a model given a certain value of said model (ownerID or something like that) Instead of showing all current rows of that model.

Thanks in advance!

Duplicated pagination

I've created a new plain project with Laravel 8, Bootstrap 4, Material Design. Footer of tables have a duplicated pagination (Next, Prev buttons). I've tried to edit layout but nothing solved this issue.

image

Problem referencing Foreign key in table

I am having issue referencing a foreign key to the name.

The model structure is as follows:

  • Class has many teachers
  • Teachers belong to class

I am now creating the teacher table to show the information associated with it including the class name. However i am only able to display the class ID(foreign key) instead of the class name.

I saw the custom value option and tried the following code to reference the name from the foreign ID via laravel eloquent relationship but to no avail.

$table->column('class')->value(function(Teacher $teacher) {
            return config('teacher.class' . $teacher->class->name);
});

Would appreciate any help!

Add table identifier

Force to set a table identifier with ->identifier(string $identifier) in order to :

  • define a table id
  • customize the rows, sort_by, sort_dir and search arguments with [identifier]_sort_by, [identifier]_sort_dir, etc => objective : allow to set custom instructions on several tables on the same page.

Migration difficulties with routes,

Hi!

We've been using laravel-tables for our project, and the upgrade to v5 seems to require significant migration, specifically in the routes department. Whereas before you could specify routes using a routes variable, now you have to create actions and pass routes to them.

Could there be a backwards-compatible option in order to reduce the migration difficulties?

Also, it seems like the row actions aren't rendering properly and the icons are missing.

image

sortable and searchable problem

Hi @Okipa
I trace in laravel-table code, after 1 hour, i found a small problem:

If you use Optional Parameters in laravel route, sortable and searchable don't work.
Example Optional Parameters route:
Route::name('products.index')->get('products/{id?}', 'ProductController@index')

Pay attention to {id?}

route parameters problem

Hello dear.
i think laravel-table has a fundamental problem it's in route.
when use a route to params, replaced 'rows','sort_by','sort_dir' instead my params
for exmaple i defined this route:
Route::name('store.products.add.index')->get('store/{storeId}/products/{orderStoreId}/aqda', 'ProductStoreController@index');
and defined index route in my controller:
$table = (new Table())->request($request)->model(ProductStore::class)-> ...... ->routes([ 'index' => ['name' => 'store.products.add.index', 'params' => [7, 2]] ])
when click on sort button i have this url:
https://site/store/20/products//aqda?sort_by=regular_price&sort_dir=desc&7&2
7 & 2 are my route parameters but they are end of url.

I trace and check your code; i found its problem.
in the Table.php file, line 282
replace this code:
array_merge(Arr::get($this->routes[$routeKey], 'params', []),$params)
instead this:
array_merge($params, Arr::get($this->routes[$routeKey], 'params', []))

thanks for you,
Mahdiyar

How to use identifier()

Hi,
I'm very sorry,
it's well described how to set an identifier for a table and when to use it
but it's missing how to implement multiple tables with their identifier inside one view.
Thanks for your support.
Christian

need to also urldecode the value in extractHiddenFieldsToGenerate

Traits/Table/HasPagination.php

line 34 needs to be

        $generatedHiddenFields[urldecode(head($argument))] = urldecode(last($argument));

Otherwise if there is a space, say, in the value of the hidden field it will be replaced with +, so (in my use case) the status of 'In Progress' , which I'm using as a filter, is hidden, and when searching on the filtered rows, the hidden field has the value "In+Progress" and the filtering breaks.

Search concatenated columns

Hi.

When I try to search users' name and surname together (like "Cawe Coy Rodrigues Marega" where users.name = 'Cawe Coy' and users.surname = 'Rodrigues Marega') I get "No results were found."

$table = (new \Okipa\LaravelTable\Table)
            ->model(\App\User::class)
            ->routes([
                'index'   => ['name' => 'admin.users.index'],
                'show'   => ['name' => 'admin.users.show'],
            ])
            ->query(function($query){
                $query->select('users.*');
                $query->addSelect(\DB::raw("CONCAT(name, ' ', surname) as full_name"));
            });
            $table->column('full_name')->sortable()->searchable('users', ['name', 'surname']);

I also tried the code below (it might be the best solution), but it throws an error:

$table->column('full_name')->sortable()->searchable();

Same for the codes below:

$table->column('full_name')->sortable()->searchable('users', ['full_name']);

$table->column('full_name')->sortable()->searchable('users', [\DB::raw("CONCAT(name, ' ', surname)")]);

How can I search concatenated columns?

pass a ready model to table

Hi
i want pass a model to table without use model() method for example:
(new Table())->model(User::class)
so, i want use like this:
$users = user::all()
(new Table())->model($users)
means i can't use eloquent in laravel-table..

thanks...

Support for Laravel 7.x^

Trying to install laravel-table into an laravel 7.3 project results in complaints from composer:

- okipa/laravel-table 1.2.0 requires illuminate/support ~5.5.0|~5.6.0|~5.7.0|~5.8.0|^6.0 -> satisfiable by illuminate/support[5.5.x-dev, ........
......
 - don't install illuminate/support v5.7.21|don't install laravel/framework v7.3.0
    - don't install illuminate/support v5.7.22|don't install laravel/framework v7.3.0
......

Error when using multiple aliases with join statements

When using multiple aliases with join statements inside the query() function of the Table class I get an error saying that The table column with related « code » database column is searchable and does not exist in the « products » (aliased as « users ») table. while in fact the products table is not aliased to anything. My query looks like this:

$builder
  ->join(
    'products',
    'products.id',
    'allocations.product_id',
  )
  ->join('sites', 'sites.id', 'allocations.site_id')
  ->join('users as agents', 'agents.id', 'allocations.agent_id')
  ->join('users as managers', 'managers.id', 'agents.parent_id')

Removing sortable and searchable from the products column works but it's not the desired result.

Custom Actions

I'm trying to understand how to create a custom button that will send a patch request action to a specific route. Is this possible with this package?

Add templates

Add templates for the lines actions html, in order to add possibility to simply override these small parts of tables instead of having to override the entire tbody.

Table generation script + architecture guide

Setup table generation script that could be like : php artisan make:table UsersTable --model=User.

This script would generate a Table class in the app/Tables directory, in which we could configure the table generation and behaviour instead of doing it in a controller or in a service.

Once it would be done, we could call our table like this in our controller :

public function index()
{
    $table = new UsersTable($request);

    return view('templates.admin.users.index', compact('table'));
}

Eager load relations

Hello.

I'm trying to Eager load on the ->query() method but:

  1. I cannot use the Builder to set Eager loading
  2. I would like to make $myModel::with('myRelation') and use it on the table afterward.

Do you know how can I manage this?

Regards

Example jQuery code for destroyConfirmationHtmlAttributes does not work

Hi,

The example jQuery code in the documentation for the destroy confirmation didn't work, not for me anyway. The message was always undefined.

What worked for me was using the jQuery 'on' method,

const destroyButton = $('form.destroy button[type="submit"]');
destroyButton.on('click', function(){
const message = $(this).data('confirm');
const form = $(this).closest('form');
if(confirm(message)) {
form.submit();
}
return false;
});

Hope this helps.

Route [templates.users.index] not defined

Hello, im recieving this error:

Route [templates.users.index] not defined. (View: E:\Laravel\vue\resources\views\vendor\laravel-table\bootstrap\rows-searching.blade.php)

My routes:

Route::get('/user', 'UsersController@index')->name('user.index');

UsersTable:

<?php

namespace App\Tables;

use Okipa\LaravelTable\Abstracts\AbstractTable;
use Okipa\LaravelTable\Table;
use App\User;

class UsersTable extends AbstractTable
{
    protected function table(): Table
    {
        return (new Table)->model(User::class)
            ->routes([
                'index' => ['name' => 'users.index'],
                'create' => ['name' => 'user.create'],
                'edit' => ['name' => 'user.edit'],
                'destroy' => ['name' => 'user.destroy'],
            ])
            ->destroyConfirmationHtmlAttributes(fn (User $user) => [
                'data-confirm' => __('Are you sure you want to delete the user :name ?', [
                    'name' => $user->name
                ])
            ]);
    }

    protected function columns(Table $table): void
    {
        $table->column('id')->sortable(true);
        $table->column('name')->sortable()->searchable();
        $table->column('email')->sortable()->searchable();
        $table->column('created_at')->dateTimeFormat('d/m/Y H:i')->sortable();
        $table->column('updated_at')->dateTimeFormat('d/m/Y H:i')->sortable();
    }
}

Controller

<?php

namespace App\Http\Controllers;


use \Illuminate\View\View;
use \App\Tables\UsersTable;
use Illuminate\Http\Request;


class UsersController extends Controller
{
    public function index(): View
    {
        $table = (new UsersTable)->setup();

        return view('templates.users.index', compact('table'));
    }
}

Suggestion: Allow diffForHumans for dateTimeFormat

diffForHumans() is a function of a Carbon DateTime object, with the current dateTimeFormat() function we can only use traditional PHP date formatting methods. This implementation would be really fantastic.

Loving this package, thanks a bunch :D

Issue when using an inner join

Hi! Just wanted to that this package is awesome and the idea behind it is just brilliant!

That being said, I'm having an issue when trying to join my "transactions" and "users" table to generate a Transactions table with user information.

  • Users table has column user.id
  • Transactions table has column transactions.user_id

I'm trying to join them in the controller like:

$transactions = (new Table)->model(Transaction::class)
            ->query(function ($query) {
                $query->whereNull('deleted_at');
                $query->join('users', 'users.id', '=', 'transactions.id');
            });

But I keep getting the error:

SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in order clause is ambiguous (SQL: select * from `transactions` inner join `users` on `users`.`id` = `transactions`.`id` where `transactions`.`deleted_at` is null order by `id` asc limit 25 offset 0)

Even without any parameters the order by id clause is being added in the query, and it's causing the issue I suppose.

How can I fix this?

I tried using an alias for the expense.id but then the Table thinks the user.id is the id for the model and it messes up all the route URLs.Can I use an alias for the users.id without using a subquery? (I'm not very good at SQL heh)

I was trying to make the users.name field searchable. Using your package, is it possible to use Eloquent to achieve this? (Include the relation and then filter the collection of the table by the given name filter?)

Thanks in advance! :)

Support for Laravel 8

Can we get laravel 8 supported?
This is why I ask and not sure if it has anything to do with it.. I am getting the following error.

Typed property Okipa\LaravelTable\Table::$tableTemplatePath must be string, null used

My Table

namespace App\Tables;
use App\Models\gamedata;
use Okipa\LaravelTable\Abstracts\AbstractTable;
use Okipa\LaravelTable\Table;

class GameTable extends AbstractTable
{
    /**
     * Configure the table itself.
     *
     * @return \Okipa\LaravelTable\Table
     * @throws \ErrorException
     */
    protected function table(): Table
    {
        return (new Table)->model(gamedata::class)
            ->routes([
                'index'   => ['name' => 'gamedatas.index'],
                'create'  => ['name' => 'gamedata.create'],
                'edit'    => ['name' => 'gamedata.edit'],
                'destroy' => ['name' => 'gamedata.destroy'],
            ])
            ->destroyConfirmationHtmlAttributes(fn(gamedata $gamedata) => [
                'data-confirm' => __('Are you sure you want to delete the line ' . $gamedata->database_attribute . ' ?'),
            ]);
    }

    /**
     * Configure the table columns.
     *
     * @param \Okipa\LaravelTable\Table $table
     *
     * @throws \ErrorException
     */
    protected function columns(Table $table): void
    {
        $table->column('game_id')->sortable()->searchable();
        $table->column('gameName')->sortable()->searchable();
        $table->column('created_at')->dateTimeFormat('d/m/Y H:i')->sortable();
        $table->column('updated_at')->dateTimeFormat('d/m/Y H:i')->sortable();
    }

    /**
     * Configure the table result lines.
     *
     * @param \Okipa\LaravelTable\Table $table
     */
    protected function resultLines(Table $table): void
    {
        //
    }

}

My Controller

public function index(Request $request)
    {
        $table = (new GameTable)->setup();
        return view('admin-games.index', compact('table'));
    }

BooleanFormatter Doesn't appear to add yes or no

Database: Postgres
Issue: Column 'Active' is data type boolean, but when formatting with BooleanFormatter, the value returned is blank. The class is setting text-danger and text-success correctly though. Do I have to populate the yes and no myself? It says in the function description that it does it automagically. I'm using standard bootstrap 5.2.3 to display the table.
My Vers.

    "require": {
        "php": "^8.0.2",
        "ccxt/ccxt": "^2.6.8",
        "guzzlehttp/guzzle": "^7.2",
        "laravel/framework": "^9.19",
        "laravel/sanctum": "^3.0",
        "laravel/tinker": "^2.7",
        "laravel/ui": "^4.2",
        "livewire/livewire": "^2.11",
        "okipa/laravel-table": "^5.2"
    },

Table:

<?php

namespace App\Tables;

use App\Models\Exchange;
use App\Models\Symbol;
use Okipa\LaravelTable\Abstracts\AbstractTableConfiguration;
use Okipa\LaravelTable\Formatters\BooleanFormatter;
use Okipa\LaravelTable\Formatters\DateFormatter;
use Okipa\LaravelTable\Table;
use Okipa\LaravelTable\Column;
use Okipe\LaravelTable\Formatters\Date;
use Okipa\LaravelTable\Filters\ValueFilter;


class SymbolsTable extends AbstractTableConfiguration
{
    protected function table(): Table
    {
        return Table::make()->model(Symbol::class)
            ->query(function($query) {
                $query->select('symbols.*');
                $query->addSelect('exchanges.name as exchange_name');
                $query->join('exchanges', 'exchanges.id', '=', 'symbols.exchange_id');
            })
            ->numberOfRowsPerPageOptions([10, 15, 20, 25]);
    }

    protected function columns(): array
    {
        return [
            Column::make('exchange_name')->title('Exchange')->sortable(),
            Column::make('symbol')->title('Symbol')->searchable()->sortable(),
            Column::make('active')->title('Active?')->sortable()
                ->format(new BooleanFormatter()),
            Column::make('created_at')->title('Created On')
                ->format(new DateFormatter('m/d/Y H:i', 'America/New_York'))
                ->sortable(),
            Column::make('updated_at')->title('Modified On')
                ->format(new DateFormatter('m/d/Y H:i', 'America/New_York'))
                ->sortable()
                ->sortByDefault('desc'),
        ];
    }

    protected function results(): array
    {
        return [
            // The table results configuration.
            // As results are optional on tables, you may delete this method if you do not use it.
        ];
    }
}

image
image

Multiple tables in one page

Hi
I realized (please correct me if I'm wrong) that is not possible to show more than one table in a page, and just the first table is shown.
Could you please tell me what can I do?

Example Controller:

...
        return view('admin.product.related-product-index', compact('table_assigned', 'table_not_assigned', 'product'));
...

Example View:

@extends('admin.layouts.list')

@section('title', 'فهرست محصولات مرتبط با «' . $product->title . '»')

@section('preTable')
    @include('flash::message')
@endsection
@section('table')
    {{ $table_assigned }}
    {{ $table_not_assigned }}
@endsection

closure must be an instance of App\Tables\Builder, instance of Illuminate\Database\Eloquent\Builder given

Hi i am building a simple crud in laravel 8 and this is what happens when i try to do a query like the ones in the docs:

Argument 1 passed to App\Tables\UsersTable::App\Tables{closure}() must be an instance of App\Tables\Builder, instance of Illuminate\Database\Eloquent\Builder given, called in /var/www/html/vendor/okipa/laravel-table/src/Traits/Table/HasAdditionalQueries.php on line 25

It works by removing Builder from this:

->query(function (Builder $query) {
        $query->where('category_id', 1);
 })

Searchable by integer column

Hello, i've been experimenting with your tables for a bit and it's great but I just noticed that I cannot search by an integer field. I see that you use lower() and cast the searchable columns to text. Could you possibly add the feature to search by a numeric or integer field ?

Multiple 'rowsConditionalClasses' entries don't work

Hi,

If you want, for example, to check a set of statuses for a model and add a css class to the row accordingly, using repeated calls to 'rowsConditionalClasses' doesn't work, and I think it's supposed to.

The addClassesToRow method of HasClasses blitzes the $model->conditionnal_classes array if the closure returns a false value, and will empty the array. I think it should really be merging the $row['classes'] into the $model->conditionnal_classes array

Propose changing to

protected function addClassesToRow(Model $model): void
{
    $model->conditionnal_classes = [];
    $this->getRowsConditionalClasses()->each(
        fn($row) => ($row['closure'])($model) ? $model->conditionnal_classes = array_merge($model->conditionnal_classes,$row['classes']) : null
    );
}

I'm going to fork this project and add this in (as i need this working now), and I'll do a pull request.

Undefined property: Okipa\LaravelTable\Table::$theadComponentPath

Working with 1 version, and not sure what happened (related to a composer update) since a week or so, but now I get this error trying to open some page using the plugin. I thought was related to new releases of plugin, but I have "okipa/laravel-table": "^1.0", on my composer.json. And in last couple of weeks I did others "composer update" commands and worked AFAIR. Some idea what could cause the issue?

(where xxxx it's the root path of the project)

PHP Fatal error: Method Illuminate\View\View::__toString() must not throw an exception, caught Facade\Ignition\Exceptions\ViewException: Undefined property: Okipa\LaravelTable\Table::$theadComponentPath (View: xxxxxxxxxxx\resources\views\vendor\laravel-table\bootstrap\table.blade.php) in xxxxxxxx\vendor\okipa\laravel-table\src\Table.php on line 0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.