Why is the angular Datatable not rendering?

I am new to Angular Datatables. How can I re-render the datatable, if it is hidden previously?

I have two components, Parent and child both hiding and showing through button clicks based on a flag.

Expected: If a new row is added through child component, I need to re-render the table.(code not written for adding new row but an emitter is applied.) Kindly help

Problem: On adding new row from child component, all rows are shown, datatabble not rendered.

Parent HTML

    <div [hidden]="!showlist">
    <table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="table table-striped table-bordered">
        <thead>
            <tr>
                <th>id</th>
                <th>title</th>
                <th>completed</th>
            </tr>
        </thead>
        <tbody>
            <tr *ngFor="let user of todo">
                <td> {{t.id}} </td>
                <td> {{t.title}} </td>
                <td> {{t.completed}} </td>
            </tr>
        </tbody>
    </table>
    <br/>

    <div class="btn-group btn-group-justified">
        <a class="btn btn-default">
            <button class="btn btn-default" (click)="showChild()">ShowChild</button>
        </a>
    </div>
</div>


<hr>
<div *ngIf="!showlist">
    <app-child (back)="showParent()" (rowAdded)="todo()">
    </app-child>
</div>

Parent ts

 export class AppComponent implements OnInit {
  constructor(private http: HttpClient) {}
  dtTrigger: Subject<any> = new Subject();
  dtOptions: DataTables.Settings = {};
  todo: Array<any>;
  showlist: boolean;   
  ngOnInit(): void {
    this.todo();
  }

  ngOnDestroy(): void {
    this.dtTrigger.unsubscribe();
  }

  apiUrl = "https://jsonplaceholder.typicode.com/todos";

  todo() {
    this.showlist = true;
    this.dtTrigger = new Subject();
    this.dtTrigger.subscribe();
    this.http.get<any[]>(this.apiUrl).subscribe(data => {
      this.todo= data;
      this.dtTrigger.next();
      this.ngOnDestroy();
    });
  }
  showChild() {
    this.showlist = false;
  }

  showParent() {
    this.showlist = true;
  }
}

Child HTML

<button class="btn btn-default" (click)="addRow()">Add row</button> &nbsp;
<button class="btn btn-default" (click)="showParent()">ShowParent</button>

Child ts

  export class ChildComponent implements OnInit {
  @Output() rowAdded: EventEmitter<any> = new EventEmitter<any>();
  @Output() back: EventEmitter<any> = new EventEmitter<any>();

  constructor() {}

  ngOnInit() {}

  addRow() {
    //code to add new row
    this.rowAdded.emit();
  }
  showParent() {
    this.back.emit();
  }
}

ALSO VIEW: STACKBLITZ DEMO CODE


Solution 1:

It looks like the issue is your variables name. They are the same.

  • todo: Array<any>;

  • todo()

Please rename one of both. And try again.

Here is a working example on stackblitz

Edit

After fix naming issue.

todo() {
    this.showlist = true;
    this.dtTrigger = new Subject();
    this.dtTrigger.subscribe();
    this.http.get<any[]>(this.apiUrl).subscribe(data => {
      console.log(data);
      this.todoList = data;
      this.dtTrigger.next();
      // remove unsubscribe after get all data.
    });
  }

Why this happened?

According with angular-datatables source code. Each time you call emit new value with dtTrigger subject. This call a internal function named this.displayTable();

dtTrigger comment

This trigger is used if one wants to trigger manually the DT rendering

  • Useful when rendering angular rendered DOM

If you unsubscribe after get data. Table go away.

Here is a working example on stackblitz

Edit 2

It looks like there is an issue with render table. It has rewrite all table and trigger this issue

Following I have detroying instance of data table and recreate new one.

Possible issue is on this line

Here is the working example