yajra / laravel-datatables

jQuery DataTables API for Laravel
https://yajrabox.com/docs/laravel-datatables
MIT License
4.76k stars 858 forks source link

Column overwrite when filter in a generated/EditColumn ? #2132

Closed franciscoarnaldog closed 5 years ago

franciscoarnaldog commented 5 years ago

Summary of problem or feature request

I have a large table (principals) with many columns and related tables. We use datatables because is easy to export and filter the data, but now JS is having problems to process the data (with only fews records ~ 1000 in an average computer can lead to 8-15 secs load time !!) So we need to use Ajax and Laravel-Datables is the solution!.

But we have problems...

When a filter is applied in a calculated column other columns get overwritten and show incorrect values, why?

Image1

Image2

Code snippet of problem

class Principal extends Model{
    protected $guarded = ['id'];
    ...
    public function proveedor(){
        return $this->belongsTo(Proveedor::class)->withDefault();
    }
}
class Proveedor extends Model {
    use SoftDeletes;
    protected $fillable =  ['user_id', 'nombre', ...];
    ...
    public function principals() {
        return $this->hasMany(Principal::class);
}
Route::get('principals', 'PrincipalsController@index');
Route::get('principals-dt', 'PrincipalsController@indexDataTables')->name('principals:dt');
use Datatables;
class PrincipalsController extends Controller {
    ...
    public function index() {
        ...
    return view('principals.index', compact( ...) );
    }    
    public function indexDataTables() {
        $query = Principal::with(..., 'proveedor', ...);
        return Datatables::eloquent($query)
            ...
            ->editColumn('proveedor.nombre', function (Principal $p) {
                return( !$p->proveedor ? '' : $p->proveedor->nombre );
            })
            ->make(true);
    }
// principals/index.blade.php
...
$('#principalsTable thead tr').clone(true).appendTo( '#principalsTable thead' );
$('#principalsTable thead tr:eq(1) th').each( function (i) {
    var title = $(this).text();
    $(this).html( '<input type="text" class="form-control form-control-sm" placeholder="'+title+'" />');
    $( 'input', this ).on( 'keyup change', function () {
        if ( table.column(i).search() !== this.value ) {
            table.column(i).search( this.value ).draw();
        }
    });
});
//  DataTable
var table = $('#principalsTable').DataTable( {
    ...
    processing: true,
    serverSide: true,
    ajax: {
        url: '{!! route('principals2:dt') !!}',
        data: function (data) {
            for (var i = 0, len = data.columns.length; i < len; i++) {
                if (! data.columns[i].search.value) delete data.columns[i].search;
                if (data.columns[i].searchable === true) delete data.columns[i].searchable;
                if (data.columns[i].orderable === true) delete data.columns[i].orderable;
                if (data.columns[i].data === data.columns[i].name) delete data.columns[i].name;
             }
             delete data.search.regex;
        }
    },
    columns: [
        { data: 'id', name: 'principals.id' },
        ...
        { data: 'proveedor.nombre' },
        ...
    ],
    ...

System details

yajra commented 5 years ago

You need to include a select statement query when using relations. See notes on demo docs https://datatables.yajrabox.com/eloquent/relationships.

$query = Principal::with(..., 'proveedor', ...)->select('principals.*');
franciscoarnaldog commented 5 years ago

ohh, thank you!