Tuesday 28 March 2017

Simple and advanced search using pipe in Angular

AngularSearchPipes

In this article I will be explaining about how to implement a simple and advanced search using pipe concept. I have explained in my previous article about how to do a simple search or filtering using angular js 1 as well. If you want to compare both implementation you can refer this link.

1. Simple search using pipe in Angular
2. Example of search using different array structure
3. Advanced search using pipe in Angular
4. Search entire Array

1. Simple search using pipe in Angular


OK, let’s start with our Angular 2 simple search implementation using pipe.

I will share the app module code as well to avoid any confusion

App module code



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

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent,FilterPipe
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }


FilterPipe is nothing but our pipe name and './pipe' is the typscript file path which has pipe code.

Let us check our component code

App component



import { Component } from '@angular/core';
import {FilterPipe} from './pipes'

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title:String;
  names:any;
  constructor(){
    this.title = "Angular 2 simple search";
        this.names = ['Prashobh','Abraham','Anil','Sam','Natasha','Marry','Zian','karan']
  }
}


Here you can see a simple array which contains some names. The template url is nothing but our html.

Template [ templateUrl: './app.component.html']



<div>
  <h3> {{title}}</h3>
  <input type="text" [(ngModel)]="queryString" id="search" placeholder="Search to type">

  <ul>
    <li *ngFor="let n of names | FilterPipe: queryString">
      {{n}}
    </li>
  </ul>
</div>


Now create a pipe and name as FilterPipe. Check below code for pipe.

Pipe


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
    transform(value: any, input: string) {
        if (input) {
            input = input.toLowerCase();
            return value.filter(function (el: any) {
                return el.toLowerCase().indexOf(input) > -1;
            })
        }
        return value;
    }
}


We are done. Run the application and start typing on text box you can see filtered result.

You can go to our GitHub page and download all the code as well. Download code from GitHub page.

2. Example of search using different array structure


Now let us check with another example, above example is searching through a simple list. We will modify our array and see how it will work.

Modified Array


this.list = [
  {name:'prashobh',age:'25'},
  {name:'Abraham',age:'35'},
  {name:'Sam',age:'45'},
  {name:'Anil',age:'15'},
  {name:'Mariya',age:'24'},
  {name:'Crock',age:'28'},
  {name:'Ram',age:'21'},
]

Modified pipe


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
    transform(value: any, input: string) {
        if (input) {
            input = input.toLowerCase();
            return value.filter(function (el: any) {
                return el.name.toLowerCase().indexOf(input) > -1;
            })
        }
        return value;
    }
}

I just updated to "el.name", it will search through the array and find the respective names. Ok now let us check with another example which can search through both age and name.


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
    transform(value: any, input: string) {
        if (input) {
            input = input.toLowerCase();
            return value.filter(function (el: any) {
                return el.name.toLowerCase().indexOf(input) > -1 ||
                    el.age.toLowerCase().indexOf(input) > -1;
            })
        }
        return value;
    }
}

You can easily update this pipe for your needs.

3. Advanced search using pipe in Angular


We have already seen how the simple search works in angular, now let us check little more advanced search. You can provide a list of parameters to pipe which you want to search. Let us check with one example.

Component code


export class AppComponent {
  title:String;
  names:any;
  constructor(){
    this.title = "Angular advanced search";
    this.list = [
   {name:'prashobh',age:'25'},
   {name:'Abraham',age:'35'},
   {name:'Sam',age:'45'},
   {name:'Anil',age:'15'},
   {name:'Mariya',age:'24'},
   {name:'Crock',age:'28'},
   {name:'Ram',age:'21'},
   ]
   this.searchableList = ['name','age']  
  }
}

There is no change except I have added a list "searchableList". This list we will be passing to our custom pipe, check below updated html for that.


<input type="text" [(ngModel)]="queryString" id="search" placeholder="Search to type">
  <ul>
    <li *ngFor="let n of list | FilterPipe: queryString : searchableList ">
      {{n.name}} ({{n.age}})
    </li>
  </ul>

We can pass array/object/string to a customer pipe, I am not explaining those in details here. Now let us check our updated pipe.

Updated pipe


import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
    transform(value: any, input: string, searchableList: any) {
        if (input) {
            input = input.toLowerCase();
            return value.filter(function (el: any) {
                var isTrue = false;
                for (var k in searchableList) {
                    if (el[searchableList[k]].toLowerCase().indexOf(input) > -1) {
                        isTrue = true;
                    }
                    if (isTrue) {
                        return el
                    }
                }
            })
        }
        return value;
    }
}

We are done, you can simply add any parameters which you want to be searchable. You can use above plunker for your testing.

4. Search entire Array


If you want your pipe to be searched for entire array, you can use below pipe.


@Pipe({
    name: 'FilterPipe'
})

export class FilterPipe implements PipeTransform {
    transform(value: any, args?: any): any {

        if (!value) return null;
        if (!args) return value;

        args = args.toLowerCase();

        return value.filter(function (item: any) {
            return JSON.stringify(item).toLowerCase().includes(args);
        });
    }
}

In this article we have discussed about doing a simple and advanced search in angular 2+ using pipe concept with different examples.

AngularSearchPipes

Related Info

1. Share data between components using a service file.

2. Create reusable component and share data between them.

3. Angular client side pagination.

4. Angular show more/less pagination

Thursday 16 March 2017

findIndex issue in IE | find index issue with different browsers

What is findIndex.

Using findIndex method we can easily find out the index of an element in the array. Let us check the code.



var list = [
  {name:'Prashobh'},
  {name:'Abraham'},
  {name:'Deepthi'}
]

var index = list.findIndex(function(e){return e.name == 'Prashobh'})

console.log(index);

Result : 0


This is the most suggested way to do this and it will work for most of the browsers. As I mentioned most of the browsers, let us check which are those browsers not supporting findIndex method.

Browser support for findIndex.



Chrome 45.0 and above: Supports

Firefox 25.0 and above: Supports

Internet Explorer: No support

Microsoft Edge: Supports

Opera: Supports

Safari 7.1 and above: Supports


So what we can do to make sure it will work in other browser as well. Let us modify our code like below.

Another approach.



var index;
list .some(function(e, i) {
    if (e.name == 'Prashobh') {
        index = i;
        return true;
    }
});

console.log(index);

Result : 0


It will work in almost all the browsers but not in IE 11. So let’s modify our code again like below.

Final one.


var index;
for (var i = 0; i < list.length; ++i) {
    if (list[i].name == 'Prashobh') {
        index = i;
        break;
    }
}
console.log(index);

Result : 0


This is basic way to do this and it will work in almost all modern browsers including IE8.

Related Post

1. HTTP status codes and meanings.

2. Jquery select all/de select all checkbox

3. How to download file from backend to UI

4. Get users browser name | get user ip address

Wednesday 15 March 2017

Get user browser name | get user ip address

It is always a good thing to collect browser info because depend on that developer can make application more usable for the user. And also we can make our application more compatible with the browser which user is using mostly.

Get browser name

Standard way is to collect user agent of the browser, see below code to get user agent info.


var browser = window.navigator.userAgent;

console.log(browser);

Eg result: 
Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 
(KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36


Above one is the most suggested way, but if you want to collect the name of the browser you can use below code.


 $(document).ready(function () {

 var browserName = 'Unknown';
 
 var isOpera = (!!window.opr && !!opr.addons) || !!window.opera 
 || navigator.userAgent.indexOf(' OPR/') >= 0;
 
 var isIE = /*@cc_on!@*/false || !!document.documentMode;
 
 var isChrome = !!window.chrome && !!window.chrome.webstore;
 
 if((!!window.opr && !!opr.addons) || !!window.opera 
 || navigator.userAgent.indexOf(' OPR/') >= 0){
  browserName = 'Opera';
 }
 if(typeof InstallTrigger !== 'undefined'){
  browserName = 'FirFox';
 }
 if(Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0){
  browserName = 'Safari';
 }
 if(/*@cc_on!@*/false || !!document.documentMode){
  browserName = 'Internet Explorer';
 }
 if(!isIE && !!window.StyleMedia){
  browserName = 'Microsoft Edge';
 }
 if(!!window.chrome && !!window.chrome.webstore){
  browserName = 'Chrome';
 }
 
 console.log(browserName);

})


Get IP of user

For collecting IP address of user, you can use below code.


$(document).ready(function () {
 
 $.getJSON("//jsonip.com/?callback=?", function (data) {
  
  var ipAddress = data.ip;
  
  console.log(ipAddress);
 });

});


Related Post

1. HTTP status codes and meanings.

2. Jquery select all/de select all checkbox

3. How to download file from backend to UI

Tuesday 14 March 2017

HTTP status codes and meanings.

We are familiar with the status codes and their meanings but sometimes will get confused as they are many. I just listed some of the status codes and their meanings below, Hope it will help you.

 

  Status 200 : 'Success',
        
  Status 201 : 'Created',
        
  Status 202 : 'Accepted',
        
  Status 203 : 'Non-Authoritative Information',
        
  Status 204 : 'No Content',
        
  Status 205 : 'Reset Content',
        
  Status 206 : 'Partial Content',
        
  Status 300 : 'Multiple Choices',
        
  Status 301 : 'Moved Permanently',
        
  Status 302 : 'Found',
        
  Status 303 : 'See Other',
        
  Status 304 : 'Not Modified',
        
  Status 305 : 'Use Proxy',
        
  Status 307 : 'Temporary Redirect',
        
  Status 400 : 'Bad Request',
        
  Status 401 : 'Unauthorized',
        
  Status 402 : 'Payment Required',
        
  Status 403 : 'Forbidden',
        
  Status 404 : 'Not Found',
        
  Status 405 : 'Method Not Allowed',
        
  Status 406 : 'Not Acceptable',
        
  Status 407 : 'Proxy Authentication Required',
        
  Status 408 : 'Request Timeout',
        
  Status 409 : 'Conflict',
        
  Status 410 : 'Gone',
        
  Status 411 : 'Length Required',
        
  Status 412 : 'Precondition Failed',
        
  Status 413 : 'Request Entity Too Large',
        
  Status 414 : 'Request-URI Too Long',
        
  Status 415 : 'Unsupported Media Type',
        
  Status 416 : 'Requested Range Not Satisfiable',
        
  Status 417 : 'Expectation Failed',
        
  Status 500 : 'Internal Server Error',
        
  Status 501 : 'Not Implemented',
        
  Status 502 : 'Bad Gateway',
        
  Status 503 : 'Service Unavailable',
        
  Status 504 : 'Gateway Timeout',
        
  Status 505 : 'HTTP Version Not Supported'
  
  
  

Related Post

1. File upload validation

2. How to download file from backend to UI

3. Jquery select all/de select all checkbox

Catch connection timeout error | catch all status code for http | get query parameter and headers from http - Angular js

It is very important to capture timeout and other errors to handle the exceptions gracefully. Angular js http provides an easy way to capture all of them. Let us check with an example.

$http call



$scope.invokeApi= function()
{
 var url = '//sampleurl'
 $http.get( url, {cache: false} )
 .success( function( data, status, headers, config )
 {
  console.log(data);
  console.log(status);
  console.log(headers());
  console.log(config);
 })
 .error( function( data,status,headers,config)
 {
  console.log(data);
  console.log(status);
  console.log(headers());
  console.log(config);
 });
}


Here data is nothing but the api response that everybody knows. Status will give status of the request call, if it is success normally gives 200 and for timeout it will be zero in the error call back. To know status codes and meanings refer this article HTTP status codes and meanings.

Headers()

headers() will give the header info of the api.

Config

config will give header information as well as other info like below.

Get query parameter from response.

Let us check with an example how to get query parameter from response.

 
 
 Example api :
 var currentTime = new Date().getTime();
 url = 'sample/get?time='+currentTime;
 
 
 

We need to read query parameter from response, let us check how the code will be.

 
 config.url // result will be full api
 config.url.split('?time=') // depending on your requirments
 
 
 

If you have only one api call you can assign to a variable and take the value easily. But if you are dealing with multiple asynchronous apis then you need to capture from the response.

Catch exceptions globally | Catch all $http status.

If you want to capture exceptions globally, we need to use some interceptor. Using this you will be able to get all status code for all api either it is success or failure. And you can easily manage the exceptions.

 
 
$httpProvider.responseInterceptors
.push(['$q', '$injector','$rootScope', function ( $q, $injector,$rootScope) {
 return function (promise) {
 return promise.then(function (response) {
  return response;
 }, function (response) {
  console.log(response); // response status
  return $q.reject(response);
 });
  };
 }]);
}]);


 
 

Related Post

1. Angular js add class to active element

2. Add and remove active class on click Angular

3. Add a class for everything clicked - angular

Thursday 9 March 2017

Angular 2 toggle button | Angular 2 collapsible panel

Let us check how we can build a toggle button using angular js 2. Same code you can use for building collapsible panel as well. It is almost similar like angular js 1 concept except some syntax changes. So if you are an angular js 1 guy, you are the best person to learn angular js2 as well :) :).

Here I have used ngif(ng-if in angular js 2) and angular 2 click method(ng-click in angular js 2) to achieve this.

Component code


@Component({
    selector: 'my-app',
    template: `<h2>{{title}}</h2>
        <button (click)="showSelected()">
            <span *ngIf="!selected">Show</span>
            <span *ngIf="selected">Hide</span>
        </button>
        <div>
            <ul *ngIf="selected">
                <li *ngFor="let i of items">
                    <p>{{i.name}} ({{i.exp}})</p>
                </li>
            </ul>
        </div>
        `
})

export class App {
    title: string;
    items: any[];
    selected: boolean;
    constructor() {
        this.title = "Angular 2 Toggle";
        this.selected = true;
        this.items = [{
            name: 'Prashobh',
            exp: '9',
        },
        {
            name: 'Abraham',
            exp: '15',
        },
        {
            name: 'George',
            exp: '2',
        },
        {
            name: 'John',
            exp: '20',
        }
        ]
    }
    showSelected(item) {
        this.selected = !this.selected;
    }
}

Related Post

1. ng-repeat in angular js 2

2. Angular 2 filter using pipe concept

3. ng-click in angular js 2

Wednesday 1 March 2017

Get selected values on click and show in the UI - Angular 2

There is lot of difference between angular one and two. Angular two is supporting JavaScript ES6 which is not yet supported by latest browsers however you can use current JavaScript ES5 with angular 2. But you may not be able to enjoy all features of angular 2 in this case. Let us check how we can show selected value on click in angular 2.

Component html


@Component({
  selector: 'my-app',
  template: `<div *ngIf="selected">
 <h4>Selected</h4>
 <p><strong>{{selected.name}}</strong></p>
</div>

<h2>{{title}}</h2>
<div>
 <ul>
  <li *ngFor="let i of items">
   <p (click)="showSelected(i)">{{i.name}} ({{i.exp}})</p>
   </li>
 </ul>
</div>
`
})

This part either you can add directly like above or move to a separate partial file and include in the component. For example like below code.


@Component({
  selector: 'my-app',
  template: `app/mayPartial.html`
})

Component logic


export class App {
    title: string;
    items: any[];
    selected:string;
    constructor() {
        this.title = "Angular 2 click";
        this.items = [{
            name:'Prashobh',
            exp:'9',
        },
        {
            name:'Abraham',
            exp:'15',
        },
        {
            name:'George',
            exp:'2',
        },
        {
            name:'John',
            exp:'20',
        }
        ]
    }
    showSelected(item){
        this.selected = item;
    }
}

Click on the names and see the result.

Related Post

1. ng-repeat in angular js 2

2. Angular 2 filter using pipe concept

3. ng-click in angular js 2

Show and hide in angular 2(+).

We all must be knowing how it was in Angular js 1. Before starting on Angular js 2, if you are interested to know how it was in Angular js 1, you can refer below posts.

1. Angular js 1 Show and hide
2. Angular js 1 loader

In angular js 1 it was ng-show and ng-hide, and also you can use ng-if as well. Let us check how it is in Angular 2.

One of the way to show and hide is using by [hidden] property


[hidden]="!showSelected"

But it is not the recommended way because it can conflict with css "display:none" property. However you can fix this by adding below css.


 [hidden] { display: none !important;}

What we can use instead of [hidden].

*ngIf is the best solution for this, let us check how we can show and hide using *ngif


@Component({
    selector: 'my-app',
    templateUrl: 'sample.html'
})

export class AppComponent {
    showSelected: boolean;
    constructor() {
        this.showSelected = false;
    }
    ShowButton() {
        this.showSelected = true;
    }
    HideButton() {
        this.showSelected = false;
    }
}


<div>
    <button (click)="ShowButton()">Show Result</button>
    <button (click)="HideButton()">Hide Result</button>
    <div *ngIf="showSelected">Result Found</div>
</div>

Click on the button and see the result.

Angular 4(+) has capable to do more things using *ngIf. You can write if else conditions in the html itself. For more info check this link : - ngIf in Angular 4(+)

In this article we have discussed about hiding and showing an element using Angular 2(+).

Related Post

1. ng-repeat in angular js 2

2. Angular 2 filter using pipe concept

3. ng-click in angular js 2