Angular data table is currently displaying an empty dataset with no information available

While attempting to display a data table in Angular JS, an issue arose where the table showed no available data despite there being 4 records present. Refer to the screenshot below for visual reference.

https://i.sstatic.net/hdaW9.png

This is the approach I took:

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 contains the following information:

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

If you have insights on what might be causing the issue or suggestions for improvement, it would greatly benefit newcomers like myself in the field of Angular JS. Thank you for your support.

Answer №1

My situation involved activating DataTables before receiving a response from the server. I found success by adding an *ngIf directive to my table element, as shown below.

<table *ngIf="dataService.users" datatable="ng" [dtOptions]="dtOptions">

Answer №2

Ensure in your user.component.ts file that you declare the data variable as empty to initialize it properly. It seems like the issue occurs when refreshing the page, possibly due to the loss of data that needs to be initialized. This could be why the datatable requires an Array and starts working once it is filled.

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

MY MISTAKE

To resolve the error message "no data available" even if there is data in the table, you need to rerender the datatable after initialization.

UPDATE

Add this variable declaration in your component:

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

After retrieving data from your service:

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 need to make modifications 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();
 });
}

Import the DataTableDirective library in your component:

    import { DataTableDirective } from 'angular-datatables';

In your app module:

    import { DataTablesModule } from 'angular-datatables';

And add it to your imports:

    imports: [
           ...,
           DataTablesModule

Lastly, for your HTML template:

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

I hope this information helps!

Source:

Answer №3

Implemented a timeout to help resolve the issue you are facing.

 setTimeout(function () {
  $(function () {
    $('#user-table').DataTable();
  });
}, 3000);

Check out this informative video I came across on YouTube: https://www.youtube.com/watch?v=78X8ZRU9Hy8

Answer №4

Avoiding the use of a Timeout function is recommended as it is not considered good practice. When working with Angular, the most effective way to address this issue is by utilizing change detection.

To implement this, start by including the instance in the constructor like so,

...
constructor(private chRef: ChangeDetectorRef) { } 
...
within the component where you intend to utilize datatables.

Next, employ the detectChanges function to ensure that Angular waits for changes (such as generating the table properly).

ngOnInit() { 
  ... 
   this.chRef.detectChanges();
   const table: any = $('table');
   this.dataTable = table.DataTable(); 
  ...
 }

This single line this.chRef.detectChanges() effectively resolves the issue at hand.

Answer №5

Recently, I encountered a similar issue and found a solution that worked for me. I'm sharing it here so that I can refer back to it in the future and potentially help others who come across the same problem.

<table *ngIf="userList.length" datatable class="table table-hover table-striped table-bordered mb-5">

I didn't find the other solutions satisfactory because I had used something similar in my previous projects and it sometimes disrupted the user experience when refreshing data. This new approach resolved the issue and is functioning correctly. I suspect the problem was caused by a delay between initialization and receiving data from the server for the datatable.

Answer №6

  1. Insert the following code in the constructor:

    private changeDetectorRef: ChangeDetectorRef
    
  2. In the user.component.ts -> getUsers(), you can include a completion function:

    this.userService.getUsers().subscribe(users => {
        this.data = users;
    },
    error => { this.errorMessage = <any>error },
    () => {
        //Finish
        this.changeDetectorRef.detectChanges();
        const table: any = $("#user-table").DataTable();
        this.dataTable = table.DataTable();
    });
    

Answer №7

The issue arises because the table is being rendered before the data is retrieved.

While not the ideal solution, one way to fix this is by adding a timeout function.

In your datatable, include *ngIf="showContent":

<table datatable="ng" *ngIf="showContent" [dtOptions]="dtOptions" class="row-border hover table-bordered">

In your component's .ts file, add the following to the ngOnInit() method:

setTimeout(()=>this.showContent=true, 250);

Also, make sure to declare the dummy variable showContent.

I hope this solution proves helpful!

Answer №8

If you're facing an issue, try implementing a length check condition in your code within the tbody element. This might just be the solution you need!👍👍👍👍

<tbody *ngIf="mainData.length">
    <tr *ngFor="let group of mainData; let i = index">
        <td>{{i+1}}</td>
        <td><img class="img-thumbnail" style="width: 100px;" src="{{imgUrl}}{{group.cat_image}}"/></td>
        <td>{{group.cat_name}}</td>
        <td>{{group.cat_slug}}</td>
        <td>
            <ul *ngFor="let item of mainData">
                <li *ngIf="group.cat_id==item.parent && item.cat_id != group.cat_id" class="d-block"><i class="bi bi-caret-right-fill"></i> {{item.cat_name}}</li>
            </ul>
        </td>
        <td>{{group.created_on}}</td>
        <td>{{group.updated_on}}</td>
        <td>
            <a href="javascript:;" class="btn btn-sm btn-primary mr-2" style="margin-right: 10px;"><i class="bi bi-pencil-square"></i></a>
            <a href="javascript:;" class="btn btn-sm btn-danger ml-2"><i class="bi bi-trash3"></i></a>
        </td>
    </tr>
</tbody>

Answer №9

As outlined in the official documentation, you can include the following css code within your styles.css:

/*
server-side-angular-way.component.css
 */
.no-data-available {
  text-align: center;
}

/*
   src/styles.css (your global style file)
*/
.dataTables_empty {
  display: none;
}

By implementing this, it ensures that the 'No Data' message will not be displayed when there is data available.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular Update Component on Input ChangeEnsuring that the component is automatically

<div class=" card-body"> <div class="row"> <div class=" font-icon-list col-lg-2 col-md-3 col-sm-4 col-xs-6 col-xs-6" routerLinkActive="active" *ngFor="let subject of subjects"> <div class=" fon ...

Create a line break in the React Mui DataGrid to ensure that when the text inside a row reaches its maximum

I'm facing an issue with a table created using MUI DataGrid. When user input is too long, the text gets truncated with "..." at the end. My goal is to have the text break into multiple lines within the column, similar to this example: https://i.sstati ...

Converting an Observable variable to a specific type in Typescript

I am currently utilizing Angular 12. To avoid duplicating the same service logic, I am experimenting with creating a base class that includes all HTTP methods and then extending a child class to utilize in the components. crud.service.ts @Injectable({ ...

Enforcing object keys in Typescript based on object values

I'm looking to design a structure where the keys of an object are based on values from other parts of the object. For example: type AreaChartData = { xAxis: string; yAxis: string; data: { [Key in AreaChartData['xAxis'] | AreaChart ...

Storing the data object in an array using Angular and Mongoose in Node.js

I've encountered an issue with my Angular form connected to Node JS and MongoDB. While some data from the form gets saved in mongoDB, there are certain fields like measurementUsed and testTolerance that do not get saved properly. This is how my model ...

Clicking the button will trigger the onclick event

I'm working on a button component in TypeScript and I have encountered an issue with passing the event to the submitButton function. import * as React from 'react'; interface Props { className?: string; text: string; onClick?(event: Reac ...

Obtaining a Bearer token in Angular 2 using a Web

I am currently working on asp.net web api and I am looking for a way to authenticate users using a bearer token. On my login page, I submit the user information and then call my communication service function: submitLogin():void{ this.user = this.l ...

Expressions without a call signature cannot be invoked

When using an adapter in the given example, I encountered a type error specifically on the last line of the getGloryOfAnimal method. Despite having clearly defined types, I am puzzled by this issue. interface ICheetah { pace: string; } interface ILio ...

Opting out of notifications using Angular's NGXS

I'm new to NGXS in Angular and have recently learned that you don't need to manually unsubscribe when using the async pipe. However, I am currently subscribing to both query parameters and dispatched actions. Do I still need to manually unsubscri ...

Angular 10 - unable to bind 'formGroup' as it is not recognized as a valid property of 'form'

In my existing Angular application, I need to implement routing and a login page as the functionality expands. To integrate routing, I have included the following code: app.module.ts // Importing various modules @NgModule({ declarations: [ App ...

What is the process for retrieving information from a retail outlet?

How can I retrieve data from the Vuex store using Vue.js? Below is my code: Vue.use(Vuex); export default new Vuex.Store({ modules: { data } }) data.js import axios from 'axios'; const state = { data: '' }; cons ...

Navigating away from a component resulted in the object being unsubscribed

I have encountered an issue while trying to implement a virtual keypad in my application. The problem occurs when navigating from my second component back to the first component. I have created a stackblitz example showcasing this error. Check out the sta ...

The return type of a getter is `any` if the object contains a method and is processed by a generic function

I am facing an issue with my code where the getter's return type is set to any, even though the actual return type should be clear. There are certain additional functions triggering this behavior: // This is necessary for reproduction const wrapperFun ...

Component that wraps around children elements and passes props to their render function

I'm currently working on coding a wrapper component that takes a title prop and a children prop which must be a function. All the other props passed to the wrapper should be used as arguments when rendering the children: import React, { ReactNode, Inp ...

Issue Encountered with @Input() in TypeScript

I'm currently working on developing an app with Angular 4 and encountered an error message when using @Input('inputProducts') products: Product[]; The specific error I received reads: [tslint] In the class "ProductListComponent", the di ...

The TypeScript compiler is unable to locate the identifier 'Symbol' during compilation

Upon attempting to compile a ts file, I encountered the following error: node_modules/@types/node/util.d.ts(121,88): error TS2304: Cannot find name 'Symbol'. After some research, I found that this issue could be related to incorrect target or l ...

Android encountered an unknown error while trying to access the URL, resulting in an HTTP failure response with a status

My Ionic app runs perfectly fine on iOS, but when I try to run it on Android, I encounter the following error: Http failure response for (unknown url): 0 Unknown Error https://i.stack.imgur.com/8EFna.png I have CORS enabled on the server side and it wor ...

The ngIf directive did not initialize the observable in the child component as expected

I'm facing an issue with CompA and CompB in my Angular project. CompA has a child component called CompB, which has an ngIf condition based on an observable that is shared between the two components. When I set this condition to true and call next on ...

Can an IonChange event be triggered from a component in Ionic 3?

Currently, I am working on developing an application that involves multiple forms. In most instances, when a user navigates back from the Confirmation view to the Form view to modify their entered data, it is essential for the form to retain the previously ...

The argument labeled as 'Subscription' cannot be assigned to the parameter labeled as 'string' in Angular

I am utilizing my Subscription variables to retrieve the API from configuration settings. public ChannelsAPI=this._configservice.getConfiguration("ChannelAPI").subscribe((result) => console.log(result)); This is the method _Configservice.getC ...