vojtasim/laravel-grid

Basic Laravel data-grid system to ease sorting and filtering large tables. Does not contain any frontend bullshit so the appearance is your job

v1.8.3 2016-04-06 08:34 UTC

This package is not auto-updated.

Last update: 2020-07-10 19:39:41 UTC


README

Basic Laravel data-grid system to ease sorting and filtering large tables. Does not contain any frontend bullshit so the apperiance is your job.

Install:

composer require vojtasim/laravel-grid

To providers in config/app.php add following line:

\VojtaSim\LaravelGrid\DataGridServiceProvider::class,

then add alias for the DataGrid facade:

'DataGrid' => \VojtaSim\LaravelGrid\Facades\DataGrid::class,

then you may publish view files by executing following command:

artisan vendor:publish --provider="\VojtaSim\LaravelGrid\DataGridServiceProvider"

Views:

Form

First we need to create form to accomodate all filter inputs. To do so, use @grid directive that takes 2 parameters.

  • Name of the grid: used in controllers or outside the @grid - @endgrid scope to reference specific grid
  • Route: route to which the filter and sort requests should be sent

@grid('products', 'products.index') - @endgrid

Sorting

Next we may add sorting column by using @gridColumn directive. This directive also takes 2 parameters.

  • Name of the column
  • Text translation
<th>@gridColumn('name', 'products.name')</th>

If you want to filter by relative model column, you will have to join the table and alias desired column.

$query->select(['products.*', DB::raw('brands.name AS brand_name')])
      ->leftJoin('brands', 'products.brand_id', '=', 'brands.id');
<th>@gridColumn('brand_name', 'products.brand')

Filters

Filter inputs are created by @gridTextFilter or @gridSelectFilter directive.

@gridTextFilter takes only 2 parameters and that is the name of the column you wish to filter and whether the filter should be precise or not (meaning whether the filter will use column like %value% or column = value

@gridTextFilter('name', true/false)

@gridSelectFilter has variety of options how you can filter column, so let`s name it:

  1. filtering by array of key => value pairs as option

    @gridSelectFilter('is_available', trans('products.availabilityStates'))

    'availabilityStates' => ['0' => 'Unavailable', '1' => 'Available],`

  2. filtering by Collection of models

    @gridSelectFilter('supplier_id', $suppliers, ['id' => 'name'])

    the 2nd parameter is the collection of models and the 3rd is array containing names of keys that should be used as key and value for each option of the select

  3. filtering by ManyToMany relationship

    @gridSelectFilter('categories:id', $categories, ['id' => 'name'])

    here, the name of column is replaced by the name of the relation we wish to filter by. The string after : is name of the column by which the relation will be queried. For example you could filter by categories like so:

    @gridSelectFilter('categories:name', $categories, ['name' => 'name'])

  4. filtering by count

    @gridSelectFilter('relatedProducts:has', trans('products.relatedFilterStates'))

    In this example the string after : is has and that means the ->has() function of QueryBuilder will be used to query the relationship.

    'relatedFilterStates' => ['=:0' => 'Unassigned', '>:0' => 'Assigned'],

    the key of each option must consist of operator and value to correcty filter the relation.

  5. filtering by multiple values

    Each of options 1. - 3. can also filter by multiple values. To do so specify the 4th parameter as true.

    @gridSelectFilter('is_available', trans('products.availabilityStates'), null, true)

    @gridSelectFilter('supplier_id', $suppliers, ['id' => 'name'], true)

    @gridSelectFilter('categories:name', $categories, ['name' => 'name'], true)

Pagination

@gridPerPage() - directive to display "per page" select

<div class="panel-body">
	{!! $products->appends(grid_parameters())->links() !!}
	<div class="pull-right">
		<label>@lang('grid.itemsPerPage')</label>
		@gridPerPage([10, 20, 50, 100])
	</div>
</div>

Helpers

grid_parameters([ string $gridName]) - returns current sorting and filtering parameters for creating routes. Ideal for creating custom action when needed.

route('products.custom_action', array_merge(['parameter' => 'value'], grid_parameters()))

grid_checkbox([ string $gridName]) - function for creating checkbox names for bulk actions

<input type="checkbox" name="{{ grid_checkbox() }}" value="{{ $product->id }}">

grid_action([ string $gridName]) - function for creating bulk action button names

<button type="submit" name="{{ grid_action() }}" value="destroy" class="btn btn-efault">
	<i class="fa fa-remove"></i>
	<span>@lang('products.destroy')</span>
</button>

grid_column_class(string|array $column [, $gridName]) - function to obrtain CSS class for specified column(s)

returns grid-filtered and/or grid-sorted

<colgroup>
	<col>
	<col class="{{ grid_column_class('name') }}">
	<col class="{{ grid_column_class(['brand_id', 'brand_name']) }}">
	<col class="{{ grid_column_class(['manufacturer_id', 'manufacturer_name']) }}">
	<col class="{{ grid_column_class('is_active') }}">
	<col>
</colgroup>

grid_clear_link([ string $gridName]) - function that returns link for clearing all filters and sorts

Controllers

In controllers you will use maily 2 functions: applyConditions() and getSelected(). You may also use getFilters() to retrieve array of filter values in column => value pairs (note: columns that are not filtered won't be included in the array)

Example #1: applying conditions and executing bulk actions

use App\Http\Controllers\Controller, Illuminate\Http\Request, VojtaSim\LaravelGrid\Services\DataGrid;

// ...

public function index(Request $request, DataGrid $grid)
{
  if ($items = $grid->getSelected('products')) {
  
    // $items = {"action": (string), "selected": (array)}
    if (method_exists($this, ($method = "{$items->action}Products"))) {
		  return $this->{$method}($request, $items->selected);
	  }
  }
  
  $query = Product::with(['brand', 'categories', 'relatedProducts'])
			->select(['products.*', DB::raw('brands.name as brand_name')])
			->leftJoin('brands', 'products.brand_id', '=', 'brands.id');

	$products = $grid->applyConditions('products', $query);

	$brands = Products\Brand::orderBy('name', 'asc')->get();
	$categories = Products\Category::orderBy('name', 'asc')->get();

  return view('products.index', compact('products', 'brands', 'categories', 'manufacturers'));
}

Example #2 - obtaining filter values

use App\Http\Controllers\Controller, Illuminate\Http\Request, VojtaSim\LaravelGrid\Services\DataGrid;

// ...

public function index(Request $request, DataGrid $grid)
{
  if ($items = $grid->getSelected('products')) {
  
    // $items = {"action": (string), "selected": (array)}
    if (method_exists($this, ($method = "{$items->action}Products"))) {
		  return $this->{$method}($request, $items->selected);
	  }
  }

	$query = Product::with(['manufacturer', 'productSeries',])
    ->select(['products.*',
      DB::raw('manufacturers.name as manufacturer_name'),
      DB::raw('printer_series.name as series_name')
    ])
    ->leftJoin('manufacturers', 'products.manufacturer_id', '=', 'manufacturers.id')
    ->leftJoin('printer_series', 'products.product_series_id', '=', 'product_series.id');
    
  $products = $grid->applyConditions('products', $query);
  
  $manufacturers = Manufacturer::orderBy('name', 'asc')->get();
  $series = Series::orderBy('name', 'asc')->get();
  
  if ($selectedManufacturers = $grid->getFilters('products', 'manufacturer_id')) {
    $series->whereIn('products_series.manufacturer_id', $selectedManufacturers);
  }
  
  $series = $series->get();
  
  return view('products.index', compact('products', 'manufacturers', 'series'));
}