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.

Angular 2 Custom Pipes

In Angular 1.x we had used Filters extensively be it inbuilt ones or the custom ones. In Angular 2.x filters have been re-branded/renamed to Pipes. Below is an example for building custom pipes in Angular 2.x.

Below is the grid for displaying list of persons and as you type in the something in search criteria it will apply that filter criteria to person name property and filter the grid items.

personlist

personfilteredlist

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, below is the code snippet for the same.

import {Pipe, PipeTransform } from '@angular/core';
@Pipe({
    name: 'personSearch'
})
export class PersonSearchPipe implements PipeTransform {
    transform(items: Array, searchValue: string){
        if (searchValue){
            return items.filter(item =>{
                if (item.name.indexOf(searchValue) > -1){
                    return true;
                }
                return false;
           })
        }
        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

personlisthtml

Attached is the source code over here, to run the source please set up angular-cli and do npm install

JavaScript function compose + ES6 Spread , REST Operators

Below is sample for compose functions using older syntax (Minus ES6)

var add10 = function(x){
  return x + 10;
}

var multiply2 = function(x){
  return x * 2;
}

var square = function(x){
  return x*x;
}

var compose = function(){
  var funcs = arguments;
  return function(){
    var args = arguments;
    for(var count=0;count<funcs.length;count++){
      args = [funcs[count].apply(this, args)];
    }
    return args[0]
  }
}

var f = compose(add10, multiply2, square);
var result = f(10);
console.log(result);

Output is 1600

Now the same can be achieved using the ES6 Spread and REST operator

var add10 = function(x){
  return x + 10;
}

var multiply2 = function(x){
  return x * 2;
}

var square = function(x){
  return x*x;
}

var compose = function(...funcs){
  return function(...args){
    for(var count=0;count<funcs.length;count++){
      args = [funcs[count](...args)];
    }
    return args[0]
  }
}

var f = compose(add10, multiply2, square);
var result = f(10);
console.log(result);

 

REST operator – ES6 introduces the rest operator, three dots (…) that precede a named parameter. That parameter is now a rest parameter that is an Array containing the rest of the parameters, hence the name. Here is the use of REST parameters from the above e.g.

var compose = function(...funcs){
  return function(...args){
    return args[0]
  }
}

One rest parameter per function, there can only be one per function and it must be the last parameter declared in the function header. Attempting to have multiple rest parameters or putting one before other parameters will throw a SyntaxError.

Spread Operator: While rest parameters use the rest operator to combine zero or more parameters into a single array parameter, the spread operator does just the opposite. It separates an array into zero or more parameters.

The spread operator looks exactly like the rest operator. It is the same three dots (…). The only difference is that it is used in function calls and array literals instead of function parameter declarations. The spread operator should be able to replace the majority, if not all, uses of apply.

At first, using the spread operator may not seem like much of an improvement over apply, besides no longer having to specify undefined or this. However, the spread operator can be used anywhere in a function call and may be used more than once as well.

Below is the example for Spread Operator from the above compose sample

args = [funcs[count](...args)];

 

ES6 + Arrow Function + Mystery with this

We have been using arrow function for quite some time in compile languages like C#, but the same is now available in java script.

An arrow function is short hand, we can leave off the function keyword and we can leave of the return statement. Even though it kind of short hand operator, but its main purposes is to get away from nuances of this keyword in javascript. First we will cover basics around arrow function then discuss nuances around this keyword.
Consider the following example

(function () {
    'use strict'
    var getName = () => "aamol";
    console.log(typeof getName);
})();

What will be the output? It is going to be function, so essentially we are declaring a function but in a short hand way. Now if we execute that function what will be the output, it would be “aamol” 

(function () {
    'use strict'
    var getName = () => "aamol";
    console.log(getName());
})();

So again as mentioned above we can leave off the return keyword in an arrow function, whatever expression is specified over there will get returned. Here is another example of arrow function

(function () {
    'use strict'
    var getName = lastName => "aamol" + " " + lastName;
    console.log(getName("gote"));
})();

So in case if we have one argument to the function then we can leave off the parenthesis. It will output “aamol gote”. Now in case if you have more than 2 parameters then we have 2 use parenthesis. Output would be the same “aamol gote”. 

(function () {
    'use strict'
    var getName = (firstName, lastName) => firstName + " " + lastName;
    console.log(getName("aamol", "gote"));
})();

Now there would be scenarios where you will have more than single expression, then how does the arrow function look like shown below, your arrow function should return some thing.

(function () {
    'use strict'
    var getName = (firstName, lastName) => {
        if (firstName && lastName) {
            return firstName + " " + lastName;
        }
        else if (firstName && !lastName) {
            return firstName;
        }
        else if (!firstName && lastName) {
            return lastName;
        }
        else {
            return null;
        }
    }
    console.log(getName("aamol", "gote"));
})();

As discussed above real purpose of arrow functions is to handle this key word within functions, “this” has always been confusing aspect of JavaScript and in ES6 arrow functions make it easier to understand. Consider following example what would be the output?

    document.addEventListener("click", function () {
        console.log(this)
    });

Output will be “#document” in chrome browser.

Whenever we have an event handler in java script, this gets set to the element that receives the event and this caused problems in ES5 because we could not get access to the context of the function. Now consider the same example with arrow function

'use strict'
document.addEventListener("click", () => console.log(this));

Output will be “#Window” in chrome browser.

We are in the global area over here and not in the context of a function so this refers to the context of code in which we running which is window a global object. So as long as we are using arrow functions this will not be set to the element that is getting the event it is going to be set to the context in the code which are running in.

Lets consider another example,

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName: function () {
        console.log(this);
    }
}
person.getName();

What would be the output, it would be person object
{age: 34, firstName: “aamol”, lastName: “gote”}

Now we will replace getName function with arrow function

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName:  () => console.log(this)
}
person.getName();

Output over here would be window object. If we were inside the function then we would get the function context

Lets take another example

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName: function(){
        return () => console.log(this)
    }
}
person.getName()();

Now in this case getName() is returning the function, so what would be the output, it would be person object, because it getName() is function and that is the context that we are working with and because we are returning the function, so this will be set to the context of invoice object.

Another important aspect for arrow functions is related to .bind, .call and .apply. Consider following example

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName: function(){
        return () => console.log(this)
    }
}

var person2 = {
    age: 36,
    firstName: "john",
    lastName: "doe",

}
person.getName().bind(person2)();

Output will be {age: 34, firstName: “aamol”, lastName: “gote”} and not person2 object. This is very important with arrow functions you cannot bind a new object to arrow functions. Javascript engine did not even throw the error, it just ignored the bind call. So when u are working with arrow functions you will not be able to change the value of this like in traditional javascript.

Like .bind similar scenario exist for .call and .apply.

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName: function(){
        return () => console.log(this)
    }
}

var person2 = {
    age: 36,
    firstName: "john",
    lastName: "doe",

}
person.getName().call(person2);

Output will be {age: 34, firstName: “aamol”, lastName: “gote”} and not person2

Same applies to .apply.

So in summary in case of arrow function .call, .bind and .apply are useless, you cannot change the value of this.

One more quirk to the arrow functions consider the following example

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName: () 
        => console.log(this)
    
}
person.getName();

This is gives an syntax error “Uncaught SyntaxError: Unexpected token =>”
New line character is problem with arrow functions you cannot put the arrow symbol on to the new line.

Arrow functions do not have “prototype” property.

'use strict'
var getName = () => "aamol";
console.log(getName.hasOwnProperty("prototype"));

Output would be false.

Whenever you declare a function in javascript it will by default have the prototype property. So unlike ES% in ES6 if you declare an function with arrow symbol, we do not have access to prototype.

Signal R Load balancing Issue

If you are using Signal R and and Signal R Hub as part of an ASP.net application which sits behind the loadbalancer with more than one machine then there is possiblity that you will start seeing this below error

SignalR – The connection id is in the incorrect format.

Just like when load balancing an ASP.NET website that uses Session, SignalR instances which are load balanced requires that all servers which handle SignalR requests must share a machine key. This is not mentioned in any documentation for SignalR/. ConnectionToken is encrypted using the machine key, when an application hits server 1 it is assigned a connectionToken generated using that machine’s machine key. If the application then hits server 2 with that assigned connectionToken, machine 2 cannot decrypt the token unless is has a matching machine key.

To solve this issue in your application web.config file you can add the machine key configuration

    
    <machineKey decryptionKey="EF1E7D088734F1B53F6594DE015FA9950B1379E4F2C3261E"
                validationKey="26EAACEB1553F966A8EC1B0304131B9D63CB81970B9204A04380189E040A84C0DC97303552434261E9445434392413EF881CF54892851955461A826805A78AA0" />

Now you must be wondering how can generate these keys, IIS manager helps you to generate those keys

  • Open IIS Manager, host you are application website on the IIS, click on the site, then on the Features view tab, select machine key as shown below
    machinekey
  • After selecting machine keys you will see following default options MachineKey1.jpg
  • Uncheck all the checkboxes and on the right side tab click on the “Generate Keys” option. machinekey2
  • Post generating the keys, Click on apply, this will add the machine key configuration web site web.config file as shown above.