1

I use angular 6 with angular-datatables.

I try to define a "rerender" button in order to reload data like this exemple :

https://l-lin.github.io/angular-datatables/#/advanced/rerender

My datatable is more complex than the one described in the exemple and I get an issue with individual columns filters use:

This is my table before rerender action with filters use, all works fine: enter image description here

But when I use these filters after data are reloaded, this is the result : My non-visible column is now visible and page info are not updated..

enter image description here

Here is my TS file :

// Lifecycle hook that is called after a component's view has been fully initialized
ngAfterViewInit() {
    console.log('ContactsComponent - ngAfterViewInit()');
    this.dtTrigger.next();
    this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
        // console.log(dtInstance);
        // console.log(dtInstance.data());
        dtInstance.columns().every(function () {
            const that = this;
            $('input', this.footer()).on('keyup change', function () {
                if (that.search() !== this['value']) {
                    that.search(this['value'])
                        .draw();
                }
            });
        });
    });

}
ngOnDestroy(): void {
    console.log('ngDestroy');
    // Do not forget to unsubscribe the event
    this.dtTrigger.unsubscribe();
}
rerender(): void {
    this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
        dtInstance.columns().every(function () {
            $('input', this.footer()).val('').change();
        });
        // Destroy the table first
        dtInstance.destroy();
        // Call the dtTrigger to rerender again
        this.dtTrigger.next();
    });
}

Here is my dtOptons config :

this.dtOptions = {
        pagingType: 'full_numbers',
        // displayLength: 10,
        // serverSide: true, // si true, execute l'appel ajax, puis l'exécute à chaque utilisation d'un des filtres
        // processing: true,
        ajax: (dataTablesParameters: any, callback) => {
            console.log('ContactsComponent - call Ajax()');
            that.selectedList = [];
            that.http.get<ApiResponse>('/api/contacts')
                .subscribe(resp => {
                    that.contactList = resp.content;
                    that.loading = false;
                    callback({
                       data: that.contactList
                    });
                },
                error => {
                    console.log('authService.login error' + error);
                        console.log('error status : ' + error.status);
                    this.myJarviaServices.showNotification('top', 'center', error,
                        'danger', 1000);
                    this.alertService.error(error);
                });
        },
        // deferRender: true,
        columns: [
            {
                // title: 'Selection',
                data: null },
            {
                // title: 'Identifiant',
                data: 'identifiant' } ,
            {
                // title: 'Nom',
                data: 'nom' },
            {
                // title: 'Prénom',
                data: 'prenom' }
            ,
            {
                // title: 'Action',
                data: null },
            {
                // title: 'Action',
                data: 'idaicontact'}
        ],
        columnDefs: [
            {
                orderable: false,
                // className: 'my_class', // classname définit une checkbox par dessus une case vide [object Object] (data: null)
                targets: [0],
                render: function(data, type, full, meta) {
                    return'<input type="checkbox" class="unique-class mat-checkbox mat-accent mat-checkbox-anim-checked-unchecked ' +
                        'mat-checkbox-inner-container mat-checkbox-inner-container-no-side-margin">';
                }
            },
            {
                targets: [4],
                visible: true,
                data: 'action',
                render: function(data, type, full, meta) {
                 return '<a class="btn btn-link btn-success btn-just-icon btn-edit" title="Editer">' +
                               '<i class="material-icons">create</i></a>' +
                        '<a class="btn btn-link btn-danger btn-just-icon btn-remove" title="Supprimer">' +
                               '<i class="material-icons">delete</i></a>' +
                        '<a class="btn btn-link btn-info btn-just-icon btn-read" title="Consulter">' +
                              '<i class="material-icons">visibility</i></a>'
                }
            },
            {
                targets: [5],
                visible: false
            }
        ],
        rowCallback: (row: Node, data: any[] | Object, index: number) => {
            const self = this;
            // Unbind first in order to avoid any duplicate handler
            // (see https://github.com/l-lin/angular-datatables/issues/87)
            // $('td:first-child', row).unbind('click');
            // $('td:first-child', row).bind('click', () => {
            const elt = $('td', row).find('[type="checkbox"]');
            if (elt) {
                elt.unbind('click');
                elt.bind('click', () => {
                    if (elt[0].checked) {
                        that.selectedList.push(data as Contact)
                    } else {
                        const itemIndex = this.selectedList.indexOf(data as Contact);
                        that.selectedList.splice(itemIndex, 1);
                    }
                    console.log(that.selectedList.length + ' éléments sélectionés');
                    this.selectedList.forEach((item) => {
                        console.log(item)
                    })
                });
            }
            const eltedit = $('td', row).find('a.btn-edit');
            if (eltedit) {
                eltedit.unbind('click');
                eltedit.bind('click', () => {
                    console.log(data);
                    this.crudContact(data, 2);
                });
            }
            const eltrem = $('td', row).find('a.btn-remove');
            if (eltrem) {
                eltrem.unbind('click');
                eltrem.bind('click', () => {
                    this.crudContact(data, 4);
                });
            }
            const eltread = $('td', row).find('a.btn-read');
            if (eltread) {
                eltread.unbind('click');
                eltread.bind('click', () => {
                    this.crudContact(data, 5);
                });
            }
            return row;
        },
        lengthMenu: [[5, 10, 25, 50, -1], [5, 10, 25, 50, 'Tous']],
        responsive: true,
        language: {
            lengthMenu: 'Afficher _MENU_ enregistrements par page',
            zeroRecords: 'Aucun contact disponible',
            info: '_START_ à _END_ sur un total de _TOTAL_ enregistrements',
            // info: ' Page _PAGE_ sur _PAGES_',
            infoEmpty: 'Aucun contact disponible',
            infoFiltered: '(filtré(s) sur _MAX_ enregistrements)',
            paginate: {
                first:      'Premier',
                last:       'dernier',
                next:       'Suivant',
                previous:   'Precedent'
            },
            search: '_INPUT_',
            searchPlaceholder: 'Recherche',

        },
        order: [[1, 'desc']],
        // Declare the use of the extension in the dom parameter
        dom: 'Blfrtip',
        stateSave: true,
        buttons: [
            {
                extend: 'print',
                className: 'btn btn-info btn-round btn-fab btn-fab-mini',
                text: '<i class="material-icons" title="Imprimer">print</i>',
                exportOptions: {
                    columns: [1, 2, 3]
                }
            },
            {
                extend: 'pdfHtml5',
                className: 'btn btn-danger btn-round btn-fab btn-fab-mini',
                text: '<i class="material-icons" title="Exporter au format pdf">save</i>',
                exportOptions: {
                    columns: [1, 2, 3]
                }
            },
            {
                extend: 'excel',
                className: 'btn btn-success btn-round btn-fab btn-fab-mini',
                text: '<i class="material-icons" title="Exporter au format xls">save</i>',
                exportOptions: {
                    columns: [1, 2, 3]
                }
            },
            {
                text: '<i class="material-icons" title="Supprimer">delete</i>',
                className: 'btn btn-danger btn-round btn-fab btn-fab-mini',
                action: function (e, dt, node, config) {
                    that.checkSelect(dt);
                }
            },
            // {
            //     text: '<i class="material-icons" title="Actualiser">replay</i>',
            //     className: 'btn btn-primary btn-round btn-fab btn-fab-mini',
            //     action: function (e, dt, node, config) {
            //         that.refresh();
            //     }
            // },
            {
                text: '<i class="material-icons" title="Nouveau">add</i>',
                className: 'btn btn-warning btn-round btn-fab btn-fab-mini',
                action: function (e, dt, node, config) {
                    that.crudContact(null, 1);
                }
            }
        ]
    };

Here is my HTML file :

<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="table table-striped table-no-bordered table-hover" cellspacing="0" width="100%" style="width:100%">
  <!--<table #dataTable class="table table-striped table-no-bordered table-hover" cellspacing="0" width="100%" style="width:100%">-->
  <tfoot>
    <tr>
      <th>Sélection</th>
      <!--<th>id</th>-->
      <th><input type="text" placeholder="Recherche Identifiant" name="search-identifiant"/></th>
      <th><input type="text" placeholder="Recherche Nom" name="search-nom"/></th>
      <th><input type="text" placeholder="Recherche prénom" name="search-prenom"/></th>
      <th>Action</th>
      <th>#</th>
    </tr>
  </tfoot>
  <thead>
    <tr>
      <th style="width: 1%">
        <mat-checkbox (change)="$event ? masterToggle() : null"
          [checked]="selection.hasValue() && isAllSelected(contactList.length)">
        </mat-checkbox>
      </th>
      <th><b>Identifiant</b></th>
      <th><b>Nom</b></th>
      <th><b>Prenom</b></th>
      <th><b>Action</b></th>
      <th><b>#</b></th>
    </tr>
  </thead>
</table>
2
  • Same issue, did you figure it out? Commented Dec 17, 2018 at 8:39
  • Yes, I post the answer Commented Dec 17, 2018 at 14:23

1 Answer 1

3

Found !

Firstly : Move filter code in method, example :

afterView() {
        this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
            // console.log(dtInstance);
            // console.log(dtInstance.data());
            dtInstance.columns().every(function () {
                const that = this;
                $('input', this.footer()).on('keyup change', function () {
                    if (that.search() !== this['value']) {
                        that.search(this['value'])
                            .draw();
                    }
                });
            });
            // dtInstance.on('search.dt', function() {
            //     // Do you stuff
            //     console.log('search: ' + dtInstance.search());
            // });
        });
    }

So when filters are applied, this method is called as following :

 ngAfterViewInit() {
    console.log('ContactsComponent - ngAfterViewInit()');
    this.dtTrigger.next();
    this.afterView();

}

When a filter is applied and that we call rerender method, we must recall this method after loading data :

 ajax: (dataTablesParameters: any, callback) => {
            console.log('ContactsComponent - call Ajax()');
            that.selectedList = [];
            that.http.get<ApiResponse>('/api/contacts')
                .subscribe(resp => {
                        that.contactList = resp.content;
                        that.loading = false;
                        // on charge la table telle qu'elle était avant le reloading (filtres éventuels)
                        this.afterView();
                        callback({
                            data: that.contactList
                        });
                    },
                    error => {
                        console.log('authService.login error' + error);
                        console.log('error status : ' + error.status);
                        this.alertService.error(error);
                        this.myJarviaServices.error(error);
                    });
        },

And it works fine !

Sign up to request clarification or add additional context in comments.

1 Comment

it worked like a charm!. BTW, I found this site very useful for those who are trying to integrate DataTables in Angular: l-lin.github.io/angular-datatables

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.