Craftable

Listing

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:

  • Frontend - the table element (blade + JS)
    • pagination feature (with per page setting)
    • sorting feature (with default sort)
    • search feature
  • Backend - AdminListing helper class to help you transform a typical request to data that auto-handle pagination, sorting & search

Basic usage

When 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:

  • ordering (=sorting)
  • searching (simple searching using SQL like operator)
  • pagination

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 sorting
  • search for searching
  • page, per_page for pagination

In 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.

Advanced usage

If above usage is too much magic for your needs, we provide couple of helper methods to build up your own listing.

Basic instance

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.

Columns to query

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>
            ...

Ordering

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

Searching

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.

Pagination

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 standard Collection.

Additional query modification

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();

Translatable models

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).