Laravel-datatables: Using Custom Filter in Datatable as a service Implementation

Created on 28 Feb 2016  ·  16Comments  ·  Source: yajra/laravel-datatables

Can somebody explain me with a simple example how to implement custom filter in Datatable as a service Implementation. I couldn't understand a thing from tutorials.

question

Most helpful comment

I'll just leave this here for anyone who is interested ;)

Javascript

$(document).ready(function () {
    $('.js-datatable-filter-form :input').on('change', function (e) {
        window.LaravelDataTables["dataTableBuilder"].draw();
    });

    $('#dataTableBuilder').on('preXhr.dt', function ( e, settings, data ) {
        $('.js-datatable-filter-form :input').each(function () {
            data[$(this).prop('name')] = $(this).val();
        });
    });
});

The extra filter data can be retrieved via the request() function. Using a scope the results can be filtered in the back-end.

Example scopes:

Archived scope

<?php namespace App\DataTables\Scopes;

use Yajra\Datatables\Contracts\DataTableScopeContract;

class ArchivedScope implements DataTableScopeContract
{
    public function apply($query)
    {
        $query->onlyTrashed();

        return $query;
    }
}

Example controller method:

public function archived(UserDataTable $dataTable)
{
    $dataTable->addScope(new App\DataTables\Scopes\ArchivedScope());

    return $dataTable->render('admin.users.index');
}

Role scope

Note the request() function in the apply method here.

<?php namespace App\DataTables\Scopes;

use Yajra\Datatables\Contracts\DataTableScopeContract;

class RoleScope implements DataTableScopeContract
{
    public function apply($query)
    {
        if ($roleId = request('role_id')) {
            $query->where('role_id', $roleId);
        }

        return $query;
    }
}

More information on the scopes can be found here: https://datatables.yajrabox.com/services/scope

All 16 comments

Let me try if I can explain it for you.

On your DT Service class you have an ajax() method that handles the ajax json response to client-side. This is the place where you transform your json response by editing/adding column, etc...

Another method is the query() method that handles your base query to be use by DT. The class has request() method that you can use to access the Request instance. See example snippet below:

    public function ajax()
    {
        return $this->datatables
            ->eloquent($this->query())
            ->addColumn('action', 'audits.audit.datatables.action')
            ->make(true);
    }

    public function query()
    {
        $audits = Audit::query();

        if ($this->request()->get('auditType')) {
            $audits->where('type', $this->request()->get('auditType'));
        }

        return $this->applyScopes($audits);
    }

Hope this helps. Will try to add more demo on service implementation soon.

Thanks. I got this part. Can you tell me how to send ajax data from client and then redraw the table ?

Hook your js on preXHR event of DT to pass custom data to server. https://datatables.net/reference/event/preXhr

Now custom filter works but pagination is not working with it.

Thanks, I solved it.

Hi Can I see an example???

See the above code snippet by @yajra. Or if you are looking for JavaScript snippet tell me.

in the above Request example with 'auditType' -- where is this posted from? the blade? can it be posted from a controller?

From the Javascript, here is the example code :

$('#dataTableBuilder')
.on('preXhr.dt', function ( e, settings, data ) {
data.auditType= $('input[name=auditType').val();
});

<input type="text" onchange="abc(this.value)" >

    function abc(a) {
        $('.datatable')
        .on('preXhr.dt', function ( e, settings, data ) {
            data.auditType = a;
        });
    }

sir, iam using datatable service too, why i cannot loaddata after onchange ..

Hi i do as follows: i catch the change event and click the reload button on datatable, like this:

$(selector).on('change',function(){
$('.buttons-reload').click();
});

Im not pretty sure its the right way to update the table, but it works.

Hi, could you please help me? Who makes the request in this case.
My view:
<input type="text" name="abc"> <div class="col-md-12"> {!! $dataTable->table(['style'=>'width:100%', 'class'=>'table table-striped table-hover']) !!} </div>
ClientsDataTable:
`
public function query()
{
$workstation_id = Auth::user()->activeWorkstation()->id;

    $clients = Client::where('workstation_id', $workstation_id)->with('addresses')->with('devices');

    if ($this->request()->get('abc')) {
        $clients->where('name', $this->request()->get('abc'));
    }


    return $this->applyScopes($clients);
}

JS:

$('#dataTableBuilder').on('preXhr.dt', function ( e, settings, data ) {
    data.abc= $('input[name=abc]').val();
});

`

Please help, I don't know who supposed to send the request.

The datatable makes the request every time you change the values on your custom filter.

You need to catch the change,keyup or keydown event on the input, like:
$(selector).on('change',function(){ $('.buttons-reload').click(); });

The buttons-reload is a button that you configure on the datatable class:
public function html() { return $this->builder() ->columns($this->getColumns()) ->addAction(['width' => '35%']) ->parameters([ 'language' => [ 'url' => '//cdn.datatables.net/plug-ins/1.10.11/i18n/Spanish.json' ], "lengthMenu" => [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]], "pagingType" => "full_numbers", 'dom' => 'lBfrtip', 'scrollX' => true, **'buttons' => [ 'reload' ],** ]); }

So when you press keys on the input, and catch the event, the datatable's reload button is clicked, then it provokes the request, the datatable class catch the input value and applies to the query you need to execute.

It works for me, but possibly is a better way to make it works.

Hi,
It did reload the query, but without passed data. Any suggestion?

It works!!! Sorry, i forgot to add on preXhr.dt on the 'on change' event like this:
$('input[name=abc]').on('change',function(){ $('#dataTableBuilder').on('preXhr.dt', function ( e, settings, data ) { data.abc= $('input[name=abc]').val(); }); $('.buttons-reload').click(); });

I'll just leave this here for anyone who is interested ;)

Javascript

$(document).ready(function () {
    $('.js-datatable-filter-form :input').on('change', function (e) {
        window.LaravelDataTables["dataTableBuilder"].draw();
    });

    $('#dataTableBuilder').on('preXhr.dt', function ( e, settings, data ) {
        $('.js-datatable-filter-form :input').each(function () {
            data[$(this).prop('name')] = $(this).val();
        });
    });
});

The extra filter data can be retrieved via the request() function. Using a scope the results can be filtered in the back-end.

Example scopes:

Archived scope

<?php namespace App\DataTables\Scopes;

use Yajra\Datatables\Contracts\DataTableScopeContract;

class ArchivedScope implements DataTableScopeContract
{
    public function apply($query)
    {
        $query->onlyTrashed();

        return $query;
    }
}

Example controller method:

public function archived(UserDataTable $dataTable)
{
    $dataTable->addScope(new App\DataTables\Scopes\ArchivedScope());

    return $dataTable->render('admin.users.index');
}

Role scope

Note the request() function in the apply method here.

<?php namespace App\DataTables\Scopes;

use Yajra\Datatables\Contracts\DataTableScopeContract;

class RoleScope implements DataTableScopeContract
{
    public function apply($query)
    {
        if ($roleId = request('role_id')) {
            $query->where('role_id', $roleId);
        }

        return $query;
    }
}

More information on the scopes can be found here: https://datatables.yajrabox.com/services/scope

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Mopster picture Mopster  ·  3Comments

ahmadbadpey picture ahmadbadpey  ·  3Comments

hohuuhau picture hohuuhau  ·  3Comments

macnux picture macnux  ·  3Comments

jackrsantana picture jackrsantana  ·  3Comments