0

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.

Kumaresan Sd
  • 1,399
  • 4
  • 16
  • 34
  • Although you have provided code of your current implementation but your statement of the question is not clear. Kindly provide a clear statement that what exactly you want to achieve so that we can help you. – Nabil Shahid Nov 13 '18 at 06:01
  • @NabilShahid, Thank you for your reply. I want detect changes inside my pipe declaration when datasource value has been changed – Kumaresan Sd Nov 13 '18 at 06:04
  • The pipe works dynamically, i.e. if the datasource changes, the pipe will be applied to the new value of the datasource. Do you want to do something else on datasource change in the pipe? – Nabil Shahid Nov 13 '18 at 06:10
  • @NabilShahid, i want use the changed datasource value inside pipe. – Kumaresan Sd Nov 13 '18 at 06:42
  • I think i got the issue. Please see my answer. – Nabil Shahid Nov 13 '18 at 09:11

1 Answers1

1

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.

Nabil Shahid
  • 1,448
  • 8
  • 11
  • in 3rd answer, i want know how can i get my datasource value in tempParam, and how can i update if datasource value changes – Kumaresan Sd Nov 13 '18 at 11:30
  • In the 3rd answer, the tempParam is only used to call the transform function of the pipe. About datasource, itis already being passed to your pipe. It will be in the `value` variable of the `transform` function. For more on how to pass parameters in pipe, see the accepted answer here: https://stackoverflow.com/questions/36816788/how-do-i-call-an-angular-2-pipe-with-multiple-arguments – Nabil Shahid Nov 13 '18 at 12:10
  • Try adding console.log the value after this line `image = value;` in the transform function, it will be the datasource i.e. `this.data`. If you are still unable to achieve what you are looking for, kindly produce a stackblitz of your current implementation and i will try to implement what you are looking for in it. – Nabil Shahid Nov 13 '18 at 12:11
  • Thank you once again. My require is In pipe decalration [DefaultPipe1 ], i have used my datasource. what i need is, if that datasource value is changed, then i have to store that changed value in one variable inside pipe declaration. – Kumaresan Sd Nov 14 '18 at 04:17
  • Hi. For storing the value in pipe, you need to make that pipe impure otherwise any variable saved in that pipe will be destroyed once the transform function of the pipe returns. However if you make the pipe impure, you can store the value but it is inefficient as i mentioned in the answer. I would suggest you to create another class instead of a pipe to perform such actions and store values instead of a pipe. – Nabil Shahid Nov 14 '18 at 08:10