Laravel-datatables: Cómo renderizar 2 tablas de datos en pestañas diferentes de una página

Creado en 12 jun. 2017  ·  9Comentarios  ·  Fuente: yajra/laravel-datatables

Resumen del problema o solicitud de función


Hola buen dia
Quiero preguntar algo y necesito su ayuda, creé una página que tenía 2 pestañas, la pestaña # una muestra datos por día, la pestaña # dos muestra datos por hora, trato de hacer la misma tabla en esas dos pestañas, pero es solo que se muestra en la pestaña # uno, en la pestaña # dos solo muestra el nombre de la columna, ¿por qué sucede esto?

Fragmento de código del problema

Sospeché que había algo incorrecto en mi controlador, este es el código:

public function index(InsightDataTable $dataTable)
    {
        return $dataTable->render('admin.report.insight.index');
    }

así que quiero preguntar cómo renderizar múltiples tablas de datos en el controlador.
Gracias.
Ah, y este es el código en mi index.blade.php

@section('content')
    @include('admin.notification')
    <div class="row">
            <div class="col-xs-12">

                <div class="nav-tabs-custom">
                    <ul class="nav nav-tabs">
                        <li class="hari"><a href="#hari" data-toggle="tab">Hari</a></li>
                        <li class="jam"><a href="#jam" data-toggle="tab">Jam</a></li>
                    </ul>
                    <div class="tab-content">

                        <div class="hari tab-pane" id="hari">
                        <div class="row">
                <div class="btn-group pull-right" style="margin: 0 15px 15px 0;">
                    <a href="" class="btn btn-primary btn-header" id="export_file">{{ trans('label.download_excel') }}</a> 
                </div>
            </div>
                <div class="box">
                <div class="box-body">
                <table border="0" cellspacing="5" cellpadding="5">
                        <tbody>
                            <tr>
                                <td>Period:&nbsp;</td>
                                <td>
                                    <input type="text" class="form-control date-range" id="" style="width: 180px;text-align: center;">
                                </td>
                            </tr>
                        </tbody>
                    </table>
                    <br/>
                    {!! $dataTable->table(['class' => 'datatable table table-striped', 'cellspacing'=>"0", 'width'=>"100%"]) !!}
                </div>
            </div>
                        </div>

                      <div class="jam tab-pane" id="jam">
                            <div class="row">
                <div class="btn-group pull-right" style="margin: 0 15px 15px 0;">
                    <a href="" class="btn btn-primary btn-header" id="export_file">{{ trans('label.download_excel') }}</a> 
                </div>
            </div>
                <div class="box">
                <div class="box-body">
                <table border="0" cellspacing="5" cellpadding="5">
                        <tbody>
                            <tr>
                                <td>Period:&nbsp;</td>
                                <td>
                                    <input type="text" class="form-control date-range" id="" style="width: 180px;text-align: center;">
                                </td>
                            </tr>
                        </tbody>
                    </table>
                    <br/>
                    {!! $dataTable->table(['class' => 'datatable table table-striped', 'cellspacing'=>"0", 'width'=>"100%"]) !!}
                </div>
            </div>
                      </div>

                    </div>
                  </div>
                </div>

            </div>
<strong i="16">@endsection</strong>

@section('custom_js')
    <script> 
        dateSelection = false;
        $('.date-range').daterangepicker();
        $('.date-range').on('apply.daterangepicker', function(ev, picker) {
            $('#dataTableBuilder').on('preXhr.dt', function ( e, settings, data ) {
                data.firstDate = picker.startDate.format('YYYY-MM-DD');
                data.lastDate = picker.endDate.format('YYYY-MM-DD');
                merge_date = data.firstDate+'_'+data.lastDate;
            });       
            var table = $('#dataTableBuilder').DataTable();
           table.ajax.reload();
           dateSelection =true;                 
        });

        $("#export_file").click(function() {
            if(dateSelection == false) {
                window.location.href = "{{ url('admin/report/insight/export/all') }}";
            } else {
                window.location.href = "{{ url('admin/report/insight/export') }}/"+merge_date;
            }
            return false;
        });

    </script>
    {!! $dataTable->scripts() !!}
<strong i="17">@endsection</strong>

Detalles del sistema

Incluya estos detalles sobre su sistema. Si se omiten, el ticket perderá prioridad sobre las solicitudes / tickets de otros usuarios.
  • Sistema operativo: Ubuntu 16.04
  • Versión PHP: 7
  • Versión de Laravel: 5.2
  • Versión de Laravel-Datatables: 6.0
question

Comentario más útil

"Un trazador de líneas:

    public function show(PrimaryDataTable $primaryDataTable, SecondDataTable $secondDataTable)
    {
        /**  Depend request we need to match proper class */
        return ${request()->get('table', 'primary') . 'DataTable'}->render(
            'resource.show',
            compact('primaryDataTable', 'secondDataTable')
        );
    }

también tenga cuidado con ajax minificado, agregue datos ajax después de llamar a este método.

Todos 9 comentarios

Sin embargo, no me gusta mucho usar un enfoque basado en servicios para una tabla y luego diferente para otra. Para ser coherente, me gustaría saber cómo separar aún más ... ¿es posible crear una estructura de este tipo ?:

UsersDatatableController
se ocupa exclusivamente de la tabla de datos para los usuarios
la vista es solo para renderizar la tabla de datos y manejar la solicitud ajax

PostsDatatableController
se ocupa exclusivamente de la tabla de datos para publicaciones (generales o relacionadas con los usuarios)
la vista es solo para renderizar la tabla de datos y manejar la solicitud ajax

UsersController
Haga uso de UsersDatatableController y PostsDatatableController para renderizar y colóquelos en la misma vista, en pestañas, sobre-debajo, lo que sea. Las llamadas ajax de las tablas de datos no serían manejadas por este controlador. Imaginar este controlador también podría ser para un formulario de edición en lugar de una página normal, con una tabla de datos dentro.

Dado que mi caso de uso es para renderizar tablas de datos del lado del servidor, buscando combinar con
https://github.com/imanghafoori1/laravel-widgetize
y esto
https://stackoverflow.com/questions/41857905/using-laravel-controllers-as-components-to-build-a-view

@yajra
Déjame saber tus pensamientos gracias

@isometriq atm, creo que no puede usar dos clases DataTable dentro de la misma ruta para el manejo de ajax de forma predeterminada. Sin embargo, tal vez pueda agregar un parámetro adicional que pueda usar para identificar qué respuesta ajax se solicita.

public function index(UsersDatatable $udt, PostsDatatable $pdt) {
  if (request()->get('table') == 'posts') {
    return $udt->render('my.view', compact('udt', 'pdt'));
  }

  return $pdt->render('my.view', compact('udt', 'pdt'));
}

A continuación, puede utilizar el constructor para ambos DT en su vista.

{!! $udt->html()->table() !!} // users table
{!! $pdt->html()->table() !!} // posts table

{!! $udt->scripts() !!} // users table scripts
{!! $pdt->scripts() !!} // posts table scripts

Solo una idea que puedes intentar explorar. ¡Gracias!

Gracias @yajra intentaré un par de cosas

Gracias por esta pregunta. Acabo de hacer que esto funcione como sugirió @yajra . Para las personas que intentan hacer lo mismo y llegaron a esta publicación, el archivo de vista debería ser:

{!! $udt->html()->table(['id' => 'udt']) !!} // users table
{!! $pdt->html()->table(['id' => 'pdt']) !!} // posts table

{!! $udt->html()->scripts() !!} // users table scripts
{!! $pdt->html()->scripts() !!} // posts table scripts

Debe pasar un atributo de identificación único a cada tabla para que js funcione correctamente. ¡Espero que esto ayude a alguien!

Y en su clase DataTable, pasó el parámetro adicional en el método html ():

public function html() {

    return $this->builder()
        ->ajax(['data' => 'function(d) { d.table = "posts"; }'])
        ->parameters($this->getBuilderParameters());
}

@yajra , sería bueno si la documentación más reciente en https://datatables.yajrabox.com/services/two-datatables tuviera este ejemplo en su lugar.

@benlwong gracias por los comentarios. El código fuente de la demostración está disponible aquí . Si puede, no dude en enviar un PR. ¡Gracias!

Hola a todos, seguí la solución en esta publicación y logré que mis dos tablas de datos funcionaran al mismo tiempo.
Pero ... no quiero que se carguen ambos al mismo tiempo, cuando se carga la página general.

Quiero que cargue la segunda tabla de datos cuando hago clic en una pestaña / botón específico.
Lo vi en la página: https://datatables.yajrabox.com/services/two-datatables

function postsDataTables() {
    if (!$.fn.dataTable.isDataTable('#postsTable')) {
        $('#postsTable').DataTable({
            dom: 'Bfrtip',
            processing: true,
            serverSide: true,
            order: [[0, 'desc']],
            buttons: [
                'csv', 'excel', 'pdf', 'print', 'reset', 'reload'
            ],
            ajax: '/services/two-datatables/posts',
            columns: [
                {data: 'id', name: 'posts.id'},
                {data: 'title', name: 'posts.title'},
                {data: 'created_by', name: 'users.name', width: '110px'},
                {data: 'created_at', name: 'posts.created_at', width: '120px'},
                {data: 'updated_at', name: 'posts.updated_at', width: '120px'},
            ],
            order: [[0, 'desc']]
        });
    }
}

Eso consiste básicamente en agregar una declaración if que envuelva el JS de datatable, pero quiero una solución a través de la implementación del servicio DataTable, como lo estabas haciendo en esta publicación. Algo como esto:

function postsDataTables() {
    if (!$.fn.dataTable.isDataTable('#postsTable')) {

        {!! $secondDataTable->html()->scripts() !!}

    }
}

Pero esto no se puede hacer porque la función "scripts ()" imprime las etiquetas