Monthly Archives: February 2017

Angular 2 Pipes – Force Angular 2 to execute Pipe

Earlier in the blogs we had seen samples of Pipes, I am referring to the sample example below again. Below is the grid for displaying list of persons and as you type in the something in multiple filters like name, email and company, that filter criteria will get applied to that persons data and filter the grid items.

blog-oioe-multiple-params-2

blog-oioe-multiple-params-3

Below is the pipes transform implementation

import {Pipe, PipeTransform } from '@angular/core';
@Pipe({
    name: 'personSearch'
})
export class PersonSearchPipe implements PipeTransform {
    transform(items: Array, nameSearch: string, emailSearch: string, companySearch: string){
        if (items && items.length){
            return items.filter(item =>{
                if (nameSearch && item.name.toLowerCase().indexOf(nameSearch.toLowerCase()) === -1){
                    return false;
                }
                if (emailSearch && item.email.toLowerCase().indexOf(emailSearch.toLowerCase()) === -1){
                    return false;
                }
                if (companySearch && item.company.toLowerCase().indexOf(companySearch.toLowerCase()) === -1){
                    return false;
                }
                return true;
           })
        }
        else{
            return items;
        }
    }
}

You need to register the pipes with the module

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { PersonSearchPipe } from './personSearch.pipe';
@NgModule({
  declarations: [
    AppComponent,
    PersonSearchPipe
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent],

})
export class AppModule { }

blog-oioe-multiple-params-1

In the above grid for displaying list of persons and as you type in the something in multiple filters like name, email and company, that filter criteria will get applied to that persons data and filter the grid items. This works perfectly fine but what if he an item is added to the filter list which matches the filter criteria then this item will not be appended to the filter list, for that to happen we have to replace the array by creating a copy of it and assigning it back to the components persons array which does not seem to be very intuitive way of doing it.

Here is the component code, I have added a setInterval which appends the person item to the array every 5 seconds on the

 ngOnInit() {
    setInterval(() => {
      this.ngzone.run(() => {
        let person = JSON.parse(JSON.stringify(this.persons[0]));
        this.persons.push(person);
        console.log("Length: " + this.persons.length);
      })
    }, 5000)
  }

Now when we have applied filter these appended elements will not be available in the UI as the pipes are not executing , so work around this we can force the pipe to be executed, this can be achieved by adding the fake filter like date time or random number to the pipe and assign the new value every time. In the above scenario I will add the Datetime to the component and pass the same to Pipe, below is the ngOnInit code

 ngOnInit() {
    setInterval(() => {
      this.ngzone.run(() => {
        let person = JSON.parse(JSON.stringify(this.persons[0]));
        this.persons.push(person);
        this.currentDatetime = new Date();
        console.log("Length: " + this.persons.length);
      })
    }, 5000)
  }

Here is the updated pipe code

import {Pipe, PipeTransform } from '@angular/core';
@Pipe({
    name: 'personSearch'
})
export class PersonSearchPipe implements PipeTransform {
    transform(items: Array<any>, nameSearch: string, emailSearch: string, companySearch: string, currentDatetime: Date){
        if (items && items.length){
            return items.filter(item =>{
                if (nameSearch && item.name.toLowerCase().indexOf(nameSearch.toLowerCase()) === -1){
                    return false;
                }
                if (emailSearch && item.email.toLowerCase().indexOf(emailSearch.toLowerCase()) === -1){
                    return false;
                }
                if (companySearch && item.company.toLowerCase().indexOf(companySearch.toLowerCase()) === -1){
                    return false;
                }
                return true;
           })
        }
        else{
            return items;
        }
    }
}

here is the updated Html

blog-force-pipe-to-execute-1

Now your filter will work like charm, as u can see “Johanna Chaney” person getting appended.

blog-force-pipe-to-execute-2

Here is the attached source code 

 

Advertisements

Angular 2 – Pipes passing multiple filters to Pipes

In earlier blog posts we had seen simplistic scenario of using pipes, but what if there is requirement to pass multiple parameters to Pipes in Angular 2,below example demonstrates the same.

Below is the grid for displaying list of persons and as you type in the something in multiple filters like name, email and company, that filter criteria will get applied to that persons data and filter the grid items.

blog-oioe-multiple-params-2

blog-oioe-multiple-params-3

For creating custom pipes you need to create class that implements PipeTransform Interface, this class is then decorated with @Pipe decorator. From the PipeTranform interface you need to implement transform method,  for passing multiple filter parameters to the pipe in the transform method you need to add those parameters like shown below in the code snippet. (nameSearch: string, emailSearch: string, companySearch: string). Transform method implementation then can decide the filtering based on the parameters passed, you can implement your own custom logic over here.

import {Pipe, PipeTransform } from '@angular/core';
@Pipe({
    name: 'personSearch'
})
export class PersonSearchPipe implements PipeTransform {
    transform(items: Array, nameSearch: string, emailSearch: string, companySearch: string){
        if (items && items.length){
            return items.filter(item =>{
                if (nameSearch && item.name.toLowerCase().indexOf(nameSearch.toLowerCase()) === -1){
                    return false;
                }
                if (emailSearch && item.email.toLowerCase().indexOf(emailSearch.toLowerCase()) === -1){
                    return false;
                }
                if (companySearch && item.company.toLowerCase().indexOf(companySearch.toLowerCase()) === -1){
                    return false;
                }
                return true;
           })
        }
        else{
            return items;
        }
    }
}

You need to register the PersonSearchPipe to component module like show below

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { PersonSearchPipe } from './personSearch.pipe';
@NgModule({
  declarations: [
    AppComponent,
    PersonSearchPipe
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent],

})
export class AppModule { }

 

In the HTML for the component add the filter like shown below

blog-oioe-multiple-params-1

 

 

Angular 2 – Passing data to child components

It is very common requirement to pass the data from Parent component to child component. In angular this can be achieved using using the @Input decorator, to define an input for a component, we use the @Input decorator. This decorator tells Angular to treat passed value as an input binding

Below is the Partner Component which has child component Partner contacts, their HTML looks some thing like this
Partner Component

{{partner.name}} {{partner.website}}
<app-partners-contacts-list [contacts]="partner.contacts"></app-partners-contacts-list>

Inside partner component we have child component partner contact list

<app-partners-contacts-list [contacts]="partner.contacts"></app-partners-contacts-list>

Partner Contact List: As u can see for the child component we are setting the partner.contacts array value to the the contacts @Input property on the child component. Child component looks some thing like this

import { Component, OnInit, Input } from '@angular/core';
import { PartnerContacts } from './../../partner.model';
@Component({
  selector: 'app-partners-contacts-list',
  templateUrl: './partners-contacts-list.component.html'
})
export class PartnersContactsListComponent implements OnInit {
  @Input() contacts: PartnerContacts[];
  constructor() { }

  ngOnInit() {
    console.log(this.contacts);
  }

}

As you can see we have declared an @Input property inside the child component so that we can set the this value from parent component.

HTML : It just a table iterating through contacts array.