Grids
Grids framework for Laravel
Both Laravel 4 and Laravel 5 are supported.
Features
- Data providers (php array, Eloquent model, Doctrine DBAL query object)
- Themes support
- Individual views for UI components
- Twitter Bootstrap v3 used by default
- Caching
- Smart input handling allows to avoid conflicts with get parameters & easily place few interactive grids on same page
- Rich customization facilities
- Component architecture
- Declarative approach
- Constructing grids via strict object oriented API or configuration in php arrays
- Rich variety of components:
- Excel and CSV export
- Records per page dropdown
- Show/hide columns UI control
- Sorting
- Filtering
- Totals calculation (sum, average value, records count, etc)
- Pagination
- etc
Upcoming Features
- Autodetecting columns based on Eloquent model (if not specified)
- Builtin output formatters for different column types
- Working with json data sources via ajax
- Check compatibility with Lumen microframework
Ask for more features. You are welcome!
Requirements
- Laravel 4.X / 5.X
- illuminate/html package if you use Laravel5.X
- php 5.4+
Installation
Composer
Step 1: Install package usingAdd nayjest/grids to "require" section of your composer.json
"require": {
"nayjest/grids": "~0.8"
},
For Laravel 5 you also need to add "illuminate/html":
"require": {
"nayjest/grids": "~0.8",
"illuminate/html": "~5"
},
Then install dependencies using following command:
php composer.phar install
Instead of editing composer.json and executing composer install you can just run following command:
For Laravel 4
php composer.phar require nayjest/grids
For Laravel 5
php composer.phar require nayjest/grids illuminate/html
Step 2: Laravel Setup
Add following line to 'providers' section of app/config/app.php file:
'Nayjest\Grids\ServiceProvider',
For Laravel 5 you also need to add "illuminate/html" service provider:
'Nayjest\Grids\ServiceProvider',
'Illuminate\Html\HtmlServiceProvider',
You may also add facade aliases to your application configuration:
'Form' => 'Illuminate\Html\FormFacade',
'HTML' => 'Illuminate\Html\HtmlFacade',
'Grids' => 'Nayjest\Grids\Grids',
Demo
Demonstration available here
Usage
Basic example
In example below grid is configured by php array using Nayjest/Builder package facilities.
$cfg = [
'src' => 'App\User',
'columns' => [
'id',
'name',
'email',
'country'
]
];
echo Grids::make($cfg);
Results available here. For more details see demo application repository
Advanced example
If you don't like plain arrays, you can construct grids using object oriented api:
Step 1. Instantiate & Configure Grid
See example below
# Let's take a Eloquent query as data provider
# Some params may be predefined, other can be controlled using grid components
$query = (new User)
->newQuery()
->with('posts')
->where('role', '=', User::ROLE_AUTHOR);
# Instantiate & Configure Grid
$grid = new Grid(
(new GridConfig)
# Grids name used as html id, caching key, filtering GET params prefix, etc
# If not specified, unique value based on file name & line of code will be generated
->setName('my_report')
# See all supported data providers in sources
->setDataProvider(new EloquentDataProvider($query))
# Setup caching, value in minutes, turned off in debug mode
->setCachingTime(5)
# Setup table columns
->setColumns([
# simple results numbering, not related to table PK or any obtained data
new IdFieldConfig,
(new FieldConfig)
->setName('login')
# will be displayed in table heder
->setLabel('Login')
# That's all what you need for filtering.
# It will create controls, process input
# and filter results (in case of EloquentDataProvider -- modify SQL query)
->addFilter(
(new FilterConfig)
->setName('login')
->setOperator(FilterConfig::OPERATOR_LIKE)
)
# optional,
# use to prettify output in table cell
# or print any data located not in results field matching column name
->setCallback(function ($val, EloquentDataRow $row) {
if ($val) {
$icon = "<span class='glyphicon glyphicon-user'></span> ";
$user = $row->getSrc();
return $icon . HTML::linkRoute('users.profile', $val, [$user->id]);
}
})
# sorting buttons will be added to header, DB query will be modified
->setSortable(true)
,
(new FieldConfig)
->setName('status')
->setLabel('Status')
->addFilter(
(new SelectFilterConfig)
->setOptions(User::getStatuses())
)
,
(new FieldConfig)
->setName('country')
->setLabel('Country')
->addFilter(
(new SelectFilterConfig)
->setName('country')
->setOptions(get_countries_list())
)
,
(new FieldConfig)
->setName('registration_date')
->setLabel('Registration date')
->setSortable(true)
,
(new FieldConfig)
->setName('comments_count')
->setLabel('Comments')
->setSortable(true)
,
(new FieldConfig)
->setName('posts_count')
->setLabel('Posts')
->setSortable(true)
,
])
# Setup additional grid components
->setComponents([
# Renders table header (table>thead)
(new THead)
# Setup inherited components
->setComponents([
# Add this if you have filters for automatic placing to this row
new FiltersRow,
# Row with additional controls
(new OneCellRow)
->setComponents([
# Control for specifying quantity of records displayed on page
(new RecordsPerPage)
->setVariants([
50,
100,
1000
])
,
# Control to show/hide rows in table
(new ColumnsHider)
->setHiddenByDefault([
'activated_at',
'updated_at',
'registration_ip',
])
,
# Submit button for filters.
# Place it anywhere in the grid (grid is rendered inside form by default).
(new HtmlTag)
->setTagName('button')
->setAttributes([
'type' => 'submit',
# Some bootstrap classes
'class' => 'btn btn-primary'
])
->setContent('Filter')
])
# Components may have some placeholders for rendering children there.
->setRenderSection(THead::SECTION_BEGIN)
])
,
# Renders table footer (table>tfoot)
(new TFoot)
->addComponent(
# TotalsRow component calculates totals on current page
# (max, min, sum, average value, etc)
# and renders results as table row.
# By default there is a sum.
new TotalsRow([
'comments',
'posts',
])
)
->addComponent(
# Renders row containing one cell
# with colspan attribute equal to the table columns count
(new OneCellRow)
# Pagination control
->addComponent(new Pager)
)
])
);
For Eager Loading of Relationships, use this syntax:
$query = Customer
->leftJoin('country', 'customers.Country', '=','country.id' )
->select('customers.*')
->addSelect('country.name as country_name')
And in the Filter config:
(new FieldConfig)
->setName('country_name')
->setLabel('Country')
->setSortable(true)
->addFilter(
(new FilterConfig)
->setOperator(FilterConfig::OPERATOR_EQ)
->setFilteringFunc(function($val, EloquentDataProvider $provider) {
$provider->getBuilder()->where('country.name', '=', $val);
})
)
,
Step 2. Render Grid
<?php echo $grid->render(); ?>
# Example below will also work as Grid class implements __toString method.
# Note that you can't forward Exceptions through __toString method on account of PHP limitations.
# Therefore you can preliminarily render grid in debug reasons and then pass resutls to view.
<?php echo $grid; ?>
# or shorter
<?= $grid ?>
# or using blade syntax (Laravel 5)
{!! $grid !!}
####Notes
- Class names in example code used without namespaces therefore you must import it before
- Grids does not includes Twitter Bootstrap css/js files to your layout. You need to do it manually Quick links:
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
- Nayjest\Grids\Components\Pager component works only with Laravel 4.X, for Laravel 5 use Nayjest\Grids\Components\Laravel5\Pager
Upgrade Guide
From 0.3.X to 0.4+
- Use THead & TFoot instead of Header & Footer components
- If you have customized grid view (grid.php), refactor it using changes in default view
- Some components became default, so you don't need to add it to configuration
Default components hierarchy:
- GridConfig
- THead
- ColumnHeadersRow
- FiltersRow
- TFoot
- OneCellRow
- Pager
For adding child components to default one, resolve it by name and use addComponent / addComponents methods.
Example:
...
(new GridConfig)
->setDataProvider($provider)
->getComponentByName(THead::NAME)
->getComponentByName(FiltersRow::NAME)
->addComponent(
(new HtmlTag)
->setTagName('button')
->setContent('Filter')
->setAttributes([
'type' => 'submit',
'class' => 'btn btn-success btn-sm'
])
->setRenderSection('filters_row_column_Actions')
)
->getParent()
->getParent()
->setColumns([
...
Note that setComponents method rewrites components structure provided by defaults.
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security related issues, please email mail@vitaliy.in instead of using the issue tracker.
License
© 2014 — 2015 Vitalii Stepanenko
Licensed under the MIT License.
Please see License File for more information.