Skip to content

Conversation

@FabienLucini
Copy link
Contributor

Add buttons to export only visible columns.

It adds the parameter 'visible_columns' in the request, so you can catch it and make your columns 'exportable' => false, in your 'getColumns' method on server side)

Example :

abstract class DataTables extends DataTable
{
    /**
     * Get columns.
     *
     * @return array
     */
    protected function getColumns()
    {

        $columns = config('datatables-columns');

        if ($this->request && in_array($this->request->get('action'), ['excel', 'csv'])) {
            if ($this->request->get('visible_columns')) {
                foreach ($columns as $column_key => $column_attr) {
                    if ($column_attr['exportable'] !== false && !in_array($column_key, $this->request->get('visible_columns'))) {
                        $columns[$column_key]['exportable'] = false;
                    }
                }
            }
        }

        return $columns;
    }
}

Add buttons to export only visible columns
Copy link

@AmirTallap AmirTallap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much, that did the trick.

@yajra yajra merged commit f06ec1d into yajra:4.0 Oct 6, 2018
@yajra
Copy link
Owner

yajra commented Oct 6, 2018

@FabienLucini @AmirTallap thanks! Released on v4.4.0 🚀

@yajra yajra added the need docs label Oct 6, 2018
@raar4ever
Copy link

$columns = config('datatables-columns');
Can you explain the code to me?
I did not understand this lineconfig('datatables-columns'); from where >> where is column return

@Namoshek
Copy link
Contributor

Namoshek commented Jun 4, 2020

It really took me some time to figure out this is a JavaScript only implementation at the moment. Because I couldn't really work out what above code does or where it would need to go, I implemented something myself in a custom base class for all my DataTables:

use Yajra\DataTables\Html\Column;
use Yajra\DataTables\Services\DataTable;

class BaseDataTable extends DataTable
{
    /**
     * Display printable view of datatables.
     *
     * @return \Illuminate\Contracts\View\View
     */
    public function printPreview()
    {
        $this->excludeNotVisiblePrintColumns();

        return parent::printPreview();
    }

    /**
     * Export results to PDF file.
     *
     * @return mixed
     */
    public function pdf()
    {
        $this->excludeNotVisiblePrintColumns();

        return parent::pdf();
    }

    /**
     * Export results to Excel file.
     *
     * @return mixed
     */
    public function excel()
    {
        $this->excludeNotVisibleExportColumns();

        /** @noinspection PhpVoidFunctionResultUsedInspection */
        return parent::excel();
    }

    /**
     * Export results to CSV file.
     *
     * @return mixed
     */
    public function csv()
    {
        $this->excludeNotVisibleExportColumns();

        return parent::csv();
    }

    /**
     * Excludes not visible columns from the request by adding them to the list of
     * excluded print columns. The same excludes are used for PDF exports.
     *
     * @return void
     */
    protected function excludeNotVisiblePrintColumns(): void
    {
        $request = $this->request();
        $columns = $this->getColumnsFromBuilder();

        if ($request->has('action') && in_array($request->get('action'), ['print', 'pdf'])) {
            if ($request->has('visible_columns')) {
                $visibleColumns = (array) $request->get('visible_columns');

                /** @var Column $column */
                foreach ($columns as $column) {
                    if (!in_array($column->name, $visibleColumns)) {
                        $this->excludeFromPrint[] = $column->name;
                    }
                }
            }
        }
    }

    /**
     * Excludes not visible columns from the request by adding them to the list of
     * excluded export columns.
     *
     * @return void
     */
    protected function excludeNotVisibleExportColumns(): void
    {
        $request = $this->request();
        $columns = $this->getColumnsFromBuilder();

        if ($request->has('action') && in_array($request->get('action'), ['excel', 'csv'])) {
            if ($request->has('visible_columns')) {
                $visibleColumns = (array) $request->get('visible_columns');

                /** @var Column $column */
                foreach ($columns as $column) {
                    if (!in_array($column->name, $visibleColumns)) {
                        $this->excludeFromExport[] = $column->name;
                    }
                }
            }
        }
    }
}

@raar4ever
Copy link

use App\Distribution;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Yajra\DataTables\Services\DataTable;

class DistributionsClientsDataTable extends DataTable
{


    /**
     * Build DataTable class.
     * <input type="checkbox" name="selected_users[]" value="{{ $id }}">
     * @param mixed $query Results from query() method.
     * @return \Yajra\DataTables\DataTableAbstract
     */
    public function dataTable($query)
    {
        
        return datatables()
            ->eloquent($query)
            ->setRowId(function($q){
                return $q->id;
            })  
             ->addColumn('edit', 'distributions.actions.edit') 

           /*  ->addColumn('check', 'distributions.actions.check') */

            ->setRowAttr(['align' => 'center'])
            ->rawColumns([
                'edit'
            ]);
            
    }

    /**
     * Get query source of dataTable.
     *
     * @param \App\DistributionsCerClient $model
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function query(Distribution $model)
    {

        $lang= LaravelLocalization::getCurrentLocale(); 
        return $model->select('distributions.*')
        ->with('products:id,name_'.$lang.'') ;
        
    }

    /**
     * Optional method if you want to use html builder.
     *
     * @return \Yajra\DataTables\Html\Builder
     */
    public function html()
    {
        return $this->builder()
                    ->setTableId('distributions-table')
                    ->columns($this->getColumns())
                    ->minifiedAjax()
                    ->dom("<'row'<'col-sm-4'l><'text-center col-sm-4'B><'col-sm-4'f>> + <'row'<'col-sm-12'tr>> + <'row'<'col-sm-5'i><'col-sm-7'p>> ")
                    ->orderBy(0)
                     ->parameters([
                       
                       'responsive'=> true ,  
                        'processing'=> "true",
                        'serverSide'=> "true", 
                        'lengthMenu' => [[10,25,50,100,-1],[10,25,50,100,'all']],
                        //////////////////////////////////////////////////////////////////////
                        'initComplete' => "function () {
                            this.api().columns([3]).every(function () {
                                var column = this;
                                var input = document.createElement(\"input\");
                                $(input).appendTo($(column.footer()).empty())
                                .on('keyup', function () {
                                    column.search($(this).val(), false, false, true).draw();
                                });
                            });
                        }",
                        
                           'buttons' => [
                           ['extend' => 'print', 'addClass' => 'btn btn-info', 'text'=>'Print'],
                                
                            ['extend' => 'excel', 'class' => 'btn btn-info', 'text'=>'Excel'], 
                            
                            ['extend' => 'colvis', 'class' => '', 'text'=>'<i class="fas fa-eye"></i>'],
                            
                           ],
                        
                        
                    ]);

    }

    /**
     * Get columns.
     *
     * @return array
     */
    protected function getColumns()
    {
        $lang= LaravelLocalization::getCurrentLocale();
        
         $columns = [
            [
                'data'  => 'id',
                'name'  => 'id',
                'title' => __('tables.id'), 
            ],
            
            [
                'data'  => 'date',
                'name'  => 'date',
                'title' => __('tables.date'),
            ],
           
             [
                'data'  => 'products.name_'.$lang.'',
                'name'  => 'products.name_'.$lang.'',
                'title' => __('tables.product'),
            ],
            
            [
                'data'  => 'number_of_products',
                'name'  => 'number_of_products',
                'title' => __('tables.numberOfProducts'),
            ],
             [
                'data'  => 'delivery_officer_id',
                'name'  => 'delivery_officer_id',
                'title' => __('tables.deliveryOfficerId'), 
             ], 
            
              [
                'data'  => 'edit',
                'name'  => 'edit',
                'title' => __('tables.edit'),
                'orderable' => false,
                'searchable' => false,
                'printable' => false,
                'exportable' => false, 
            ],   
        ]; 
        return $columns;
    }

    

    /**
     * Get filename for export.
     *
     * @return string
     */
    protected function filename()
    {
        return 'DistributionsClients_' . date('YmdHis');
    }
}

This my code how i can add the function >> @Namoshek Thanks bro

@Namoshek
Copy link
Contributor

Namoshek commented Jun 5, 2020

@raar4ever You can implement the export of visible columns only by copying over the methods of my example into your table. I would recommend creating a common (abstract) base class for all of your DataTables though. In that case you would place the methods in that class.

Important is that you do not enable the button excel in the html() method for example, but postExcelVisibleColumns instead. It will use http POST to perform the request, which means your table must be set up for POST requests (see documentation). Maybe you can also override the buttons.server-side.js file locally and add excelVisibleColumns as button using GET. Then you don't really need to change anything. Not sure if this is that simple though. Using POST has the advantage that the query string of your requests does not get too large, which in return requires changing proxy settings, etc.

@yajra yajra changed the title Update buttons.server-side.js ServerSide export with ColVis integration. Jun 6, 2020
@glultra
Copy link

glultra commented Jan 13, 2024

Hello @FabienLucini @yajra
I know it's too late that I face the same issue here can anyone checkout my code please ?

 public function html()
    {
        $dataTable = $this->setBuilder('documents-table', 2)
            ->parameters([
                'initComplete' => 'function () {
                    window.LaravelDataTables["documents-table"].buttons().container()
                     .appendTo( "#table-actions")
                 }',
                'fnDrawCallback' => 'function( oSettings ) {
                   $(".select-picker").selectpicker();
                 }',

            ]);

        if (canDataTableExport()) {
            $dataTable->buttons(
                Button::make([
                    'extend' => 'excel',
                    'text' => '<i class="fa fa-file-export"></i> ' . trans('app.exportExcel'),
                    'exportOptions' => [
                        'columns' => ':visible',
                    ],
                ]),
                Button::make([
                    'extend' => 'pdf',
                    'text' => '<i class="fa fa-file-pdf"></i> ' . trans('app.exportPdf'),
                    'exportOptions' => [
                        'columns' => ':visible',
                    ],
                ]),
                Button::make([
                    'extend' => 'print',
                    'text' => '<i class="fa fa-print"></i>' . trans('app.print'),
                ])->exportOptions([
                       'columns' => ':visible',
                ]),
                Button::make([
                    'extend' => 'colvis',
                    'text' => '<i class="fa fa-columns"></i> ' . trans('app.columnSelector'),
                ]),

            );
        }


        return $dataTable;
    }
    
    protected function getColumns()
    {
        $data = [
            'check' => [
                'title' => '<input type="checkbox" name="select_all_table" id="select-all-table" onclick="selectAllTable(this)">',
                'exportable' => false,
                'orderable' => false,
                'searchable' => false
            ],
            '#' => ['data' => 'DT_RowIndex', 'orderable' => false, 'searchable' => false, 'visible' => false, 'title' => '#'],
            __('app.ref') => ['data' => 'id', 'name' => 'id', 'title' => __('app.ref')],
            __('modules.employees.employeeId') => Column::computed('user.name')
                ->title(__('modules.employees.employeeId'))
                ->data('employee')
                ->orderable(true)
                ->exportable(false),
            __('app.nationality') => ['data' => 'nationality', 'name' => 'nationality', 'title' => __('app.nationality'), 'exportable' => false],
            __('modules.project.documentId') => ['data' => 'document_id', 'name' => 'document_id', 'exportable' => false, 'title' => __('modules.projects.documentId')],
            __('app.name') => ['data' => 'document_name', 'name' => 'document_name', 'exportable' => false, 'title' => __('app.name')],
            __('modules.projects.documentType') => Column::computed('document_type')
                ->title(__('modules.projects.documentType'))
                ->data('document_type')
                ->orderable(true)
                ->exportable(false),
            __('modules.employees.issueDate') => Column::computed('document_issue_date')
                ->title(__('modules.employees.issueDate'))
                ->data('document_issue_date')
                ->orderable(true)
                ->exportable(false),
            __('modules.employees.expiryDate') => Column::computed('document_expiry_date')
                ->title(__('modules.employees.expiryDate'))
                ->data('document_expiry_date')
                ->orderable(true)
                ->exportable(false),
            __('modules.employees.attachments') => Column::computed('attachments')
                ->title(__('modules.employees.attachments'))
                ->data('attachments')
                ->exportable(false),

        ];

        $action = [
            Column::computed('action', __('app.action'))
                ->exportable(false)
                ->printable(false)
                ->orderable(false)
                ->searchable(false)
                ->addClass('text-right pr-20')
        ];

        return array_merge($data, CustomFieldGroup::customFieldsDataMerge(new EmployeeDocument()), $action);

    }

@glultra
Copy link

glultra commented Jan 13, 2024

And these are my versions =>
"yajra/laravel-datatables-buttons": "^10.0",
"yajra/laravel-datatables-html": "^10.8",
"yajra/laravel-datatables-oracle": "^10.8"

@glultra
Copy link

glultra commented Mar 1, 2024

Hey everyone after been a quite a research i found my issue and applying the method mentioned above

 protected function excludeNotVisibleExportColumns(): void
    {
        $request = $this->request();
        $columns = $this->getColumnsFromBuilder();

        if ($request->has('action') && in_array($request->get('action'), ['excel', 'csv'])) {
            if ($request->has('visible_columns')) {
                $visibleColumns = (array) $request->get('visible_columns');

                /** @var Column $column */
                foreach ($columns as $column) {
                    if (!in_array($column->name, $visibleColumns)) {
                        $this->excludeFromExport[] = $column->name;
                    }
                }
            }
        }

    }

but i got another issue visible_columns was never sent with the request so i read buttons.server-side.js functionality and figured out that weather from server side request or client side request this code can fix your issues:

  • Server side rendering
  public function html()
    {
        $dataTable = $this->setBuilder('documents-table', 2)
            ->parameters([
                'initComplete' => 'function () {
                    window.LaravelDataTables["documents-table"].buttons().container()
                     .appendTo( "#table-actions");
                 }',
                'fnDrawCallback' => 'function( oSettings ) {
                   $(".select-picker").selectpicker();
                 }',
                'columnDefs' => '[
                    { visible: false, targets: 1 }
                 ]',

            ]);

        if (canDataTableExport()) {
            $exportOptions = ['columns' => ':visible'];

            $dataTable->buttons(
                Button::make([
                    'extend' => 'excel',
                    'text' => '<i class="fa fa-file-export"></i> ' . trans('app.exportExcel'),
                ])->action("function (e, dt, button, config) {
                     var visibleColumns = dt.columns(':visible').indexes().toArray();

                    // Map the visible columns to column data
                    var columnData = visibleColumns.map(function (index) {
                        return dt.settings()[0].aoColumns[index].data;
                    });

                    var url = dt.ajax.url() || '';

                    var params = dt.ajax.params();
                    params.action = 'excel';
                    params._token = $('meta[name=\"csrf-token\"]').attr('content');
                    params.visible_columns = columnData;

                    if (url.indexOf('?') > -1) {
                        return url + '&' + $.param(params);
                    }

                    url = url + '?' + $.param(params);

                    window.location = url;
                }")->exportOptions($exportOptions),
                Button::make([
                    'extend' => 'pdf',
                    'text' => '<i class="fa fa-file-pdf"></i> ' . trans('app.exportPdf'),
                ])->exportOptions($exportOptions),
                Button::make([
                    'extend' => 'print',
                    'text' => '<i class="fa fa-print"></i>' . trans('app.print'),
                ])->exportOptions($exportOptions),
                Button::make([
                    'extend' => 'colvis',
                    'text' => '<i class="fa fa-columns"></i> ' . trans('app.columnSelector'),
                    'columnText' => 'function ( dt, idx, title ) {
                return (idx+1)+": "+title;
            }'
                ]),
            );
        }


        return $dataTable;
    }
  • Client side rendering
$(document).ready(function () {
            var table = $('#documents-table').DataTable();

            // Define the Excel button with customization for selected columns export
            var excelButton = {
                extend: 'excel',
                text: 'Export Selected Columns',
                action: function (e, dt, button, config) {
                    // Get the list of visible columns
                    var visibleColumns = dt.columns(':visible').indexes().toArray();

                    // Map the visible columns to column data
                    var columnData = visibleColumns.map(function (index) {
                        return dt.settings()[0].aoColumns[index].data;
                    });
                   // @method _buildUrl  function(dt, action){}
                    var url = dt.ajax.url() || '';

                    var params = dt.ajax.params();
                    params.action = 'excel';
                    params._token = $('meta[name="csrf-token"]').attr('content');
                    params.visible_columns = columnData;

                    if (url.indexOf('?') > -1) {
                        return url + '&' + $.param(params);
                    }

                    url = url + '?' + $.param(params);

                    window.location = url;
                }
            };

            // Create DataTable buttons
            var buttons = new $.fn.dataTable.Buttons(table, {
                buttons: [
                    {
                        extend: 'colvis',
                        text: 'Column Visibility'
                    },
                    excelButton
                ]
            });

            // Add the buttons to an existing container
            buttons.container().appendTo($('.buttons-container'));
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants