Search code examples
laraveldatatablesmetronic

Conditionally hide datatable column based on data-attribute


I have the following problem:

I want to conditionally display a column in a datatable. Specifically the actions column in a kt-datatable. (Metronic theme for Laravel has it's own implementation of Datatables which is based on jQuery datatables.) I have been looking at the column.render method but i can't quite make sense of it. Ideally i would like to display a column based on a data-attribute i pass along with the html of the datatable.

HTML:

<div id="datatable-example" data-isadmin="{{ auth()->user()->hasRole(['superadmin', 'admin']) }}"></div>

js/jquery:

example_datatable = example_element.DataTable({
        search: {
            input: $('#generalSearch'),
        },
        rows: {
            ...
        },
        columns: [
            ...,
            {
                field: 'actions',
                title: sendings_element.data('column-actions'),
                class: 'w8',
                textAlign: 'right',
                sortable: false,
                template: function (row) {
                    if (sendings_element.data('user_roles')) {
                        return '<a class="btn btn-danger" href="' + sendings_element.data('route-edit-sending').replace('__id__', row.id) + '">' + sendings_element.data('text_edit') + '</a>';
                    } else {
                        return '<a class="btn btn-danger" href="' + sendings_element.data('route-view-sending').replace('__id__', row.id) + '">' + sendings_element.data('text_view') + '</a>';
                    }
                }
            },
        ],
    });

I really would appreciate some help for this.

update:

I found a kinda workable solution:

<div id="datatable-id"
         ...
         data-isadmin="{{ auth()->user()->hasRole('super-admin') ? "true"  : "false" }}" 
    ></div>

and in my javascript:

 kb_datatable = kb_element.customDataTableThatExtendsKTDatatable({      
        ...    
        columns: [          
           ...
            {
                field: 'description',
                title: kb_element.data('column-description'),
                width: 600,
                template: function(row) {
                    if(kb_element.data('isadmin')){                     
                        kb_datatable.column(1).visible(false);
                    }
                },
            },           
            ...

            },
        ],
    });

I'm not happy yet with the solution because i'm using a template for a row to hide the column. But it works for now.

@remul : Yes i am using the KT-Datatable, i'm not sure my co-worker that reported this problem does in his code. Good catch! I've just set up a testcase using a custom datatable that extends the ktdatatable. I have accepted your answer as the solution since you pointed me in the right direction but the thing is the visible property expects a true or a false, hence the shortif in the html code. Ideally i would like a callback function for the column but the only thing i can find that somewhat resembles it is the template method. Also if i use the result of the shortif on the visible property in the column object i run into a weird bug where i need to set the other columns to null and can't set additional properties for other columns. Using ColumnDefs with target and visible was proposed as another solution but i can't make that work yet either.


Solution

  • Adding the visible attribute to the actions column should do the trick, but when using stateSave changing the data-attribute would have no effect as long there is a saved state for the datatable. To avoid this you can remove the visibility from the state save as mentioned here:

    If you want to not state save column visibility you could remove the visible parameter from the columns array of objects in the state object:

    stateSaveParams: function ( settings, data ) {
      for ( var i=0, ien=data.columns.length ; i<ien ; i++ ) {
        delete data.columns[i].visible;
      }
    }
    

    So in your case:

    columns: [
        {
            field: 'actions',
            visible: !!example_element.data('isadmin')
            // your other attributes
        },
    ],
    stateSaveParams: function ( settings, data ) {
        for ( var i=0, ien=data.columns.length ; i<ien ; i++ ) {
            delete data.columns[i].visible;
        }
    }