How can i watch value change in angular 4?

388 Views Asked by At

I have created custom pipe for my component [grid]. Inside pipe declaration i can take my component instance but at same time i want get if my data-source value changes inside the pipe declaration. Is it possible to get that?

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { GridAllModule } from '@syncfusion/ej2-angular-grids';
import { NumericTextBoxAllModule } from '@syncfusion/ej2-angular-inputs';
import { ToolbarModule } from '@syncfusion/ej2-angular-navigations';

import { AppComponent, DefaultPipe, DefaultPipe1 } from './app.component';

@NgModule({
  declarations: [
    AppComponent,
    DefaultPipe,
    DefaultPipe1
  ],
  imports: [
    BrowserModule, GridAllModule, ToolbarModule, NumericTextBoxAllModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

platformBrowserDynamic().bootstrapModule(AppModule);

app.component.ts

   
import {
  NgModule, Component, Pipe, PipeTransform, OnInit, Input, IterableDiffers, DoCheck,
  ViewChild, ChangeDetectorRef, SimpleChanges, WrappedValue, SimpleChange, OnChanges
} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { orderDetails } from './data';
import { orderDetails1 } from './datas';
import { GridComponent } from '@syncfusion/ej2-angular-grids';

// import { SidebarService } from './service';


@Pipe({ name: 'defaultImage' })
export class DefaultPipe implements PipeTransform {
  transform(value: string, fallback: string, ): string {
    let image = '';
    if (value) {
      image = value;
    } else {
      image = fallback;
    }
    return image;
  }
}

@Pipe({
  name: 'defaultImage1',
  pure: false
})
export class DefaultPipe1 implements PipeTransform {

  constructor(private _ref: ChangeDetectorRef) { }

  transform(value: string, fallback: string, ): string {
     // let Data1 = '';
// if (value.length !== 0) {
//   Data1 = value;
// } else {
//   Data1 = fallback;
// }
// return Data1;
  }
}

@Component({
  selector: 'app-my',
  template: `
  <img [src]="imageUrl | defaultImage:'http://s3.amazonaws.com/uifaces/faces/twitter/sillyleo/128.jpg':true"/>

  <div class="control-section">
    <ejs-grid #gridref id='check' [dataSource]='data | defaultImage1:gridref' height='350'>
    <e-columns>
    <e-column field='OrderID' headerText='Order ID' textAlign='Right' width=90></e-column>
    <e-column field='CustomerID' headerText='Customer ID' width=120></e-column>
    <e-column field='Freight' headerText='Freight' textAlign='Right' format='C2' width=90></e-column>
    <e-column field='OrderDate' headerText='Order Date' textAlign='Right' format='yMd' width=120></e-column>
</e-columns>
    </ejs-grid>
</div>
 `
})
export class AppComponent implements OnInit, DoCheck {
  imageUrl: String = '';

  public data: Object[] = [];


  @ViewChild('gridref')
  public refGrid: GridComponent;



  ngOnInit(): void {
    this.data = orderDetails;

  }

 
}

In here, i have initialize my pipe like below:

<ejs-grid #gridref id='check' [dataSource]='data | defaultImage1:gridref' height='350'>

I have tried like this [ http://blog.bogdancarpean.com/how-to-watch-for-changes-an-arrayobject-on-angular-2/ ] but i am not able to achieve my requirement

  @Input() data: Object[] = [];

  differ: any;
  constructor(differs: IterableDiffers) {
    this.differ = differs.find([]).create(null);
  }
  ngDoCheck() {
    const change = this.differ.diff(this.data);
    console.log(change);
  }

In this case, how can i achieve my requirement. Please provide any idea.

1

There are 1 best solutions below

5
On

There are two types of pipes. Pure and Impure. In case of pure pipe, the transform function of pipe is only called when angular detects a change in value or arguments passed to a pipe. In impure pipe, it is called for every change detection cycle no matter whether the value or arguments of the pipes change. As your pipe is pure, the transform function is not calling because datasource is an array of objects so angular is not detecting its value being modified because value i.e. data is an array, not a primitive type i.e.(string, boolean, int e.t.c) There are three ways you can fix this issue:

1.Execute the following lines of code after the data in your logic changes which will assign a new object to data, which will call the pipe i.e. trasnform function of pipe will execute and you will get the new value of datasource in it:

var tempVar= this.data; 
this.data= []; 
Object.assign(this.testVal, tempVar);

Simply Run the above three lines whenever you update this.data i.e.

2.Change your pipe to impure. However it will be inefficient because the transform will be called every time angular runs change detection making your application slower. You can do it like this i.e. set pure flag to false in the @Pipe decorator:

@Pipe({
  name: 'defaultImage',
  pure: false
})
  1. Use a temp primitive type argument for the pipe and update its value on the change of data which will cause the transform function of pipe to execute with new datasource e.g. in your html:

Add it to the transform function i.e.:

transform(value: string, fallback: string, tempParam)

And change its value whenever the data is changed in your logic.