Laravel-datatables: How to render 2 datatable in one page different tabs

Created on 12 Jun 2017  ·  9Comments  ·  Source: yajra/laravel-datatables

Summary of problem or feature request


Hi, good day to you.
I wanna ask something and need your help, i created page that had 2 tabs, tab #one is showing data per day, tab #two is showing data per hour, i try to make the same table in that two tabs, but its only showing in tab #one, in tab #two only showing name of column, why this happen?

Code snippet of problem

i suspected the wrong thing is in my controller, this is the code:

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

so i wanna ask how to render multiple datatable in controller.
Thankyou.
Oh and this is the code in my 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>
@endsection

@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() !!}
@endsection

System details

  • Operating System: Ubuntu 16.04
  • PHP Version: 7
  • Laravel Version: 5.2
  • Laravel-Datatables Version: 6.0
question

Most helpful comment

"One" liner:

    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')
        );
    }

also be carefull with minified ajax, add ajax data after calling this method.

All 9 comments

However, i don't like very much to use service-based approach for a table then different for another. For consistent, i would like to know how to separate even further ..is it possible to create such a structure?:

UsersDatatableController
exclusively takes care of the datatable for users
the view is only for rendering the datatable and handling ajax request

PostsDatatableController
exclusively takes care of the datatable for posts (general or related to users)
the view is only for rendering the datatable and handling ajax request

UsersController
Make use of the UsersDatatableController and PostsDatatableController for rendering and place them in the same view, in tabs, over-under, whatever.. ajax calls of the datatables would not be handled by this controller. Envisionning this controller could also be for an edit form instead of a normal page, with a datatable inside it.

Since my use case is for rendering serverside datatable, looking to combine with
https://github.com/imanghafoori1/laravel-widgetize
and this
https://stackoverflow.com/questions/41857905/using-laravel-controllers-as-components-to-build-a-view

@yajra
Lemme know your thoughts thx

@isometriq atm, I think you cannot use two DataTable class within the same route for ajax handling by default. However, maybe you can add additional param that you can use to identify which ajax response is being requested.

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'));
}

You can then use the builder for both DT on your view.

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

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

Just an idea that you can try exploring. Thanks!

Thanks @yajra i'll try a couple things

Thanks for this question. I just got this to work as @yajra suggested. For people who are trying to do the same thing and landed on this post, the view file should be:

{!! $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

You need to pass in an unique id attribute to each table so the js will work properly. Hope this help somebody!

And in your DataTable class, you passed in the additional param in the html() method:

public function html() {

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

@yajra, would be nice if the latest documentation on https://datatables.yajrabox.com/services/two-datatables have this example instead.

@benlwong thanks for the feedback. The demo source code is available here. If you can, please do not hesitate to submit a PR. Thanks!

Hi all, I followed the solution on this post and I achieved my two datatables working at the same time!
But.. I don't want that are loaded both at the same time, when the general page is being loaded.

I want that to load the 2nd datatable when I click a specific tab/button.
I saw that in the page: 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']]
        });
    }
}

That consists basically to add a if statement wrapping the JS of datatable, but I want a solution through DataTable Service implementation, like you were doing in this post. Something like this:

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

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

    }
}

But this can't be done because the function "scripts()" print the tags itself.

I don't know if what I'm asking is very easy to solve, or I'll have to write manually the JavaScript of the datatable and dispense DataTable Service in the second table.

Thanks for your attention. @yajra

I have tried to use your suggestion but i got an error Method Yajra\DataTables\Html\Builder::html does not exist. . Did i miss something? @benlwong

"One" liner:

    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')
        );
    }

also be carefull with minified ajax, add ajax data after calling this method.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Mopster picture Mopster  ·  3Comments

jackrsantana picture jackrsantana  ·  3Comments

techguydev picture techguydev  ·  3Comments

sangnguyenplus picture sangnguyenplus  ·  3Comments

t0n1zz picture t0n1zz  ·  3Comments