Listing is the very core feature of every administration area. It provides an overview on your data represented by Eloquent models.
Every listing consist of:
AdminListing
helper class to help you transform a typical request to data that auto-handle pagination, sorting & searchWhen you are creating a CRUD interface, you probably need an admin listing displaying all the rows of your data represented by an Eloquent model. You usually want such listing to be sortable, searchable and paginable.
Our helper AdminListing
covers typical scenario of such requirements including:
like
operator)It's basically just a layer built on top of the query builder, but it speeds up a development a lot. The usage is very simple:
use AdminListing;
class MoviesController extends Controller
{
public function index(Request $request)
{
// create and AdminListing instance for a specific model and
$data = AdminListing::create(Movie::class)
->processRequestAndGet(
// pass the request object
$request,
// set columns to query
['id', 'title', 'published_at'],
// set columns to searchIn
['id', 'title', 'body']
);
if ($request->ajax()) {
return ['data' => $data];
}
return view('admin.movie.index', ['data' => $data]);
}
AdminListing automatically process these query parameters from request:
orderBy
, orderDirection
for sortingsearch
for searchingpage
, per_page
for paginationIn your resources/views/admin/movie/index.blade.php
file you should use pre-generated movie-listing
Vue component that should plug&play nicely with the AdminListing output.
{danger.fa-exclamation-triangle} AdminListing does not provide any request authorization nor validation, so you should handle that on your own.
If above usage is too much magic for your needs, we provide couple of helper methods to build up your own listing.
Use get()
method to get basic listing with no additional features (searching, pagination, sorting, ...):
class MoviesController extends Controller
{
public function index(IndexMovie $request)
{
$data = AdminListing::create(Movie::class)
->get();
$data
now holds a standard Collection
of Eloquent model objects.
You can pass an array of columns to the get
method just like in standard query builder.
class MoviesController extends Controller
{
public function index(IndexMovie $request)
{
$data = AdminListing::create(Movie::class)
->get(['id', 'name']);
These should be reflected on the frontend as well.
Here it's your resources/views/admin/movie/index.blade.php
:
...
<table class="table table-hover table-listing">
<thead>
<tr>
<th :column="'id'">{{ trans('admin.movie.columns.id') }}</th>
<th :column="'title'">{{ trans('admin.movie.columns.name') }}</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in collection">
<td>@{{ item.id }}</td>
<td>@{{ item.name }}</td>
...
To build listing with ordering functionality, use attachOrdering()
method:
class MoviesController extends Controller
{
public function index(IndexMovie $request)
{
$data = AdminListing::create(Movie::class)
->attachOrdering($request->sortBy, $request->sortDirection)
->get();
To limit the sortable columns you want to update the request class app/Http/Requests/Admin/Article/IndexArticle.php
:
public function rules()
{
return [
'orderBy' => 'in:id,name|nullable',
...
];
}
Don't forget to make them available on the frontend using sortable
property on th
tag in your resources/views/admin/movie/index.blade.php
:
...
<table class="table table-hover table-listing">
<thead>
<tr>
<th is='sortable' :column="'id'">{{ trans('admin.movie.columns.id') }}</th>
<th is='sortable' :column="'title'">{{ trans('admin.movie.columns.name') }}</th>
...
and in your
AdminListing supports simple full-text search in your Eloquent models. You just need to specify the columns you want to be searched in using attachSearch()
. The searched phrase is tokenized and each token is searched individually in all columns.
class MoviesController extends Controller
{
public function index(IndexMovie $request)
{
$data = AdminListing::create(Movie::class)
->attachSearch($request->queryString,
// specify an array of columns to search in
['id', 'name', 'body']
)
->get();
{danger.fa-exclamation-triangle} Searching is currently available only for text attributes and primary key.
To build listing with pagination functionality, use attachPagination()
method:
class MoviesController extends Controller
{
public function index(IndexMovie $request)
{
$data = AdminListing::create(Movie::class)
->attachPagination($request->currentPage)
->get();
{info} If you use pagination functionality, object of
Pagination\LengthAwarePaginator
is returned instead of standardCollection
.
In some cases you still need to modify query a bit (i.e. add some filters). In that case you can use modifyQuery()
method:
class MoviesController extends Controller
{
public function index(IndexMovie $request)
{
$data = AdminListing::create(Movie::class)
->modifyQuery(function($query) use ($request){
if ($request->has('author_id')) {
$query->where('author_id', $request->author_id);
}
})
->get();
AdminListing supports translatable models as well (see How to make your model translatable). You don't have to set up anything.
By default it uses a default locale, but you can override it using setLocale()
:
class MoviesController extends Controller
{
public function index(IndexMovie $request)
{
$data = AdminListing::create(Movie::class)
->setLocale('fr')
->get();
You can now work with ordering or search just like with non-translatable model and the AdminListing takes care of all the translation stuff. Returned $data
variable is holding a collection of models that has locale set up correctly (i.e. in the example above returned JSON is going to be translated in French).