Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to render 2 datatable in one page different tabs #1202

Closed
faisalhilmi opened this issue Jun 12, 2017 · 9 comments
Closed

How to render 2 datatable in one page different tabs #1202

faisalhilmi opened this issue Jun 12, 2017 · 9 comments
Labels

Comments

@faisalhilmi
Copy link

faisalhilmi commented Jun 12, 2017

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
@isometriq
Copy link

@isometriq
Copy link

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

@yajra
Copy link
Owner

yajra commented Jun 20, 2017

@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!

@yajra yajra added the question label Jun 20, 2017
@isometriq
Copy link

Thanks @yajra i'll try a couple things

@yajra yajra closed this as completed Jul 6, 2017
@benlwong
Copy link

benlwong commented Dec 21, 2017

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.

@yajra
Copy link
Owner

yajra commented Dec 22, 2017

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

@manelsanz
Copy link

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 <script></script> 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

@RayhanYulanda
Copy link

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

@mgralikowski
Copy link
Contributor

mgralikowski commented Dec 3, 2020

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

@github-actions github-actions bot locked and limited conversation to collaborators Oct 14, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

7 participants