Alaksandar Jesus Gene
Alaksandar Jesus Gene

Reputation: 6883

How to pass attribute value change to angular 4 directive

I am trying to implement Datatable in my angular 4 application. I created an directive and the data table is populating.

Now if i delete the table data, i could see visual disapperance of the row but datatable still holds my data. The solution to it is the directive should detect change in the data.

Will it be costly if using setInterval in the directive as it will be running an infinite loop.

Or the other idea i got was create attribute draw and redraw. But again the question how to keep a track on change in input attribute with no events occured.

HTML Code

<table class="table table-striped table-bordered" appDatatable [data]="roles" *ngIf="roles && roles.length">
  <thead>
    <tr>
      <th>Role</th>
      <th>Description</th>
      <th>Created By</th>
      <th>Created At</th>
      <th>Updated By</th>
      <th>Updated At</th>
      <th>Actions</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let role of roles">
      <td>{{role.name}}</td>
      <td>{{role.description}}</td>
      <td>{{role.created_by}}</td>
      <td>{{role.created_at | date}}</td>
      <td>{{role.updated_by}}</td>
      <td>{{role.updated_at}}</td>
      <td class="text-center">
        <button class="btn btn-primary btn-sm" type="button" (click)="update(role)">
          <span class="fa fa-pencil"></span>
        </button>
        <button class="btn btn-danger btn-sm" type="button" (click)="remove(role)">
          <span class="fa fa-trash"></span>
        </button>
      </td>
    </tr>
  </tbody>
</table>

Directive Code

import { Directive, ElementRef, Input, OnChanges } from '@angular/core';

declare var jQuery:any;

@Directive({
  selector: '[appDatatable]'
})
export class DatatableDirective implements OnChanges {

    table:any;

  @Input() data:any;

  constructor(private el: ElementRef) { 
    this.initializeDataTable();

  }

   initializeDataTable(){
        setTimeout(()=>{
           this.table =  jQuery(document).find(this.el.nativeElement).DataTable();
           setInterval(()=>{this.watchData();}, 5000);
       });
  }

  watchData(){
   //I can watch the data change here. But is it a costly solution?
  }

  ngOnChanges(){ // not working
    console.log(this.data);
  }

}

Hope i was clear on my question.

In short, how to detect change in input to a directive.

Upvotes: 2

Views: 1381

Answers (2)

Alaksandar Jesus Gene
Alaksandar Jesus Gene

Reputation: 6883

Thanks to all your efforts. Need to put setTimeout in component.js file.

roles.component.ts

onRemoveConfirm(row){

    _.remove(this.roles, (role)=> role === row);
    this.setDatatable();  

  }

setDatatable(){
     this.drawDatatable = false;
     setTimeout(() => { // added this setTimeout 
      this.drawDatatable = true;  
    });
   }

role.component.html Here instead of passing data, took a boolean info to draw the table.

<table class="table table-striped table-bordered" appDatatable [draw]="drawDatatable">

Directive

import { Directive, ElementRef, Input, OnInit, OnChanges } from '@angular/core';

declare var jQuery:any;

@Directive({
  selector: '[appDatatable]'
})
export class DatatableDirective implements OnInit, OnChanges {

    table:any;

  @Input() draw:boolean;

  constructor(private el: ElementRef) { 


  }

  ngOnInit(){
    this.setTable();
  }

  ngOnChanges(){
      this.setTable();
  }

   initializeDataTable(){
        setTimeout(()=>{
           this.table =  jQuery(document).find(this.el.nativeElement).DataTable();
       });
  }

  setTable(){
     if(!this.draw){
      if(this.table){
        this.table.destroy();
        this.table = undefined;
      }
      return;
    }
    if(!this.table){
      this.initializeDataTable();
    }

  }


}

Upvotes: 0

zgue
zgue

Reputation: 3850

The signature of the ngOnChanges function is like

ngOnChanges(changes: SimpleChanges) {

}

Or is your post pseudo code? You have to add SimpleChanges to your imports.

import { Directive, ElementRef, Input, OnChanges, SimpleChanges } from '@angular/core';

Upvotes: 1

Related Questions