Search code examples
angulartypescriptdatatable

Data table is showing no data available in table using Angular


When I was trying to show data table in angular js. It shows no data available in table but there are 4 records in table. See screenshot below.

enter image description here

Here's what I did.

user.component.ts

import { Component, OnInit } from '@angular/core';

import { UserModel }         from './user-model';
import { UserService }       from './user.service';
declare var $ :any;

@Component({
  selector: 'user-page',
  template: require('./user.component.html'),
  providers: [ UserService ]
})

export class UserComponent implements OnInit {

  data: any;
  errorMessage: string;

 constructor(private userService:UserService){ }

 ngOnInit() { 
  this.getUsers();
 }

 getUsers() {  
 this.userService.getUsers()
                 .subscribe(
                   users => {this.data = users; 
                              $(function(){
                               $("#user-table").DataTable();
                              });
                            },
                   error =>  this.errorMessage = <any>error);
  }
}

user.service.ts

import { Injectable }              from '@angular/core';
import { Http, Response }          from '@angular/http';
import { Headers, RequestOptions } from '@angular/http';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

import { UserModel } from './user-model';

@Injectable()
export class UserService {
      private usersUrl = 'http://localhost/larang/public/api/users';  
constructor (private http: Http) {}

getUsers(): Observable<UserModel[]> { 
 return this.http.get(this.usersUrl)
                .map(this.extractData)
                .catch(this.handleError);
}


private extractData(res: Response) { 
  let body = res.json();

  return body.data || { };
}

private handleError (error: Response | any) { console.log(error);

 let errMsg: string;
 if (error instanceof Response) {
  const body = error.json() || '';
  const err = body.error || JSON.stringify(body);
  errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
 } else {
   errMsg = error.message ? error.message : error.toString();
 }
console.error(errMsg);
return Observable.throw(errMsg);
 }
}

user.component.html

<table id="user-table" class="table table-bordered table-hover">
 <thead>
      <tr>
        <th>Name</th>
        <th>Email</th>
        <th>Added On</th>
      </tr>
 </thead>
 <tbody>
       <tr *ngFor="let item of data">
         <td>{{item.name}}</td>
         <td>{{item.email}}</td>
         <td>{{item.added}}</td>
       </tr>
 </tbody>
</table>

this.data looks like this

[
 {"name":"John Doe","email":"john.doe@gmail.com","added":"2017-04-26"},
 {"name":"Ramkishan","email":"Ramkishan@gmail.com","added":"2017-04-26"},
 {"name":"Jason Bourne","email":"jason@gmail.com","added":"2017-04-26"},
 {"name":"RK","email":"ramkishan.suthar@ranosys.com","added":"2017-04-26"}
]

What I am doing wrong please help. It will be very helpful for newbies in Angular JS like me.


Solution

  • In your user.component.ts, declare your data var empty to initialize it. I don't know why but I had the same problem when I refresh the page. I think the data is lost so you need to initialize it. Maybe datatable needs to know there is an Array and after you fill it it's working.

        ngOnInit(){
            this.data = [];
            this.getUsers();
        }
    

    I WAS WRONG

    You have to rerender the datatable because if you rerender the initialisation throw an error, that's why you have the message saying "no data available" despite you have in the table.

    UPDATE

    In your component, declare this variable:

      @ViewChild(DataTableDirective)
      dtElement: DataTableDirective;
      dtOptions: DataTables.Settings = {};
      dtTrigger: Subject<any> = new Subject();
    

    after you pull your data from whatever service you have:

    this.officeSrv.getAll().subscribe((data) => {
      console.log('----> office service : get all data', data);
      this.offices = data.offices;
    
      // ADD THIS
      this.dtTrigger.next();
    
    }, (err) => {
      console.log('-----> err', err);
    })
    

    If you have modification to make modification directly in the same datatable without changing the page create and call this function

    rerender(): void {
     this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
       // Destroy the table first
       dtInstance.destroy();
       // Call the dtTrigger to rerender again
       this.dtTrigger.next();
     });
    }
    

    Use this library in your component:

        import { DataTableDirective } from 'angular-datatables';
    

    In your app module:

        import { DataTablesModule } from 'angular-datatables';
    

    And declare this :

        imports: [
               ...,
               DataTablesModule
    

    And finally for your templating (HTML):

       <table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="table table-hover table-striped table-bordered" cellspacing="0"
          width="100%">
          <thead>
            <tr>
              <th>Nom</th>
              <th>Adresse</th>
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>
            <tr *ngFor="let office of offices">
              <td>{{office.name}}</td>
              <td>{{office.adress}}</td>
              <td>
                <div class="btn-group">
                  <button type="button" class="btn btn-block btn-info">Action</button>
                  <button type="button" class="btn btn-primary btn-outline-info dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"
                    aria-haspopup="true" aria-expanded="false">
                  <span class="sr-only">Toggle Dropdown</span>
                </button>
                  <div class="dropdown-menu">
                    <a class="dropdown-item" (click)="update(office._id)">Mettre à jour</a>
                    <a class="dropdown-item" (click)="delete(office._id)">Supprimer</a>
                  </div>
                </div>
              </td>
            </tr>
          </tbody>
        </table>
    

    Hope that's help

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