Monday, 23 October 2017

Format date using pipe and append local time zone - Angular

Angular 2(+)Angular4/5Date FilteringLocal time zone

Since most of the countries have different time zone and date time, it is important to show local time zone for users. Let us check how we can format a date and append a local time zone along with that. I will be creating a simple pipe and append the local time zone along with that. I will be adding local time zone logic into a service file, advantage is that you can easily inject and use it anywhere.

Angular pipe


import { Pipe, PipeTransform } from '@angular/core';
import { DatePipe } from '@angular/common';
import { userDataService } from './userDataService';

@Pipe({
    name: 'dateFormatPipe',
})
export class dateFormatPipe implements PipeTransform {
    timeZone:string;
    constructor(public _userData: userDataService) {
        var date = new Date();
        this.timeZone = this._userData.getLocalTimeZone(date);
    }
    transform(value: string) {
        var datePipe = new DatePipe("en-US");
        value = datePipe.transform(value, 'MMM dd yyyy') +' '+ this.timeZone;
        return value;
    }
}

Above is a simple pipe which will format the date, I have written more about this, if interested you can check this link (date filtering and formatting using pipe). And I have injected a service file which will be giving the local time zone. Let us check service file code

Service


import { Injectable } from '@angular/core';

@Injectable()
export class userDataService {
 _timezone: any = null;
 _timeZoneAbbr: any
 getLocalTimeZone(dateInput: any) {
   if (this._timezone) return this._timezone;

   var dateObject = dateInput || new Date(),
   dateString = dateObject + ""

   this._timeZoneAbbr = (
     dateString.match(/\(([^\)]+)\)$/) ||
     dateString.match(/([A-Z]+) [\d]{4}$/)
   );

  if (this._timeZoneAbbr) {
   this._timeZoneAbbr = this._timeZoneAbbr[1].match(/[A-Z]/g).join("");
  }

  if (!this._timeZoneAbbr && /(GMT\W*\d{4})/.test(dateString)) {
   return RegExp.$1;
  }

  this._timezone = this._timeZoneAbbr;
  return this._timeZoneAbbr;
 };

}

You can read more about services here: Communicate between a component and a service file and Share data between components using service file.

Finally our html


<p>{{currentTime | dateFormatPipe}}</p>

Dont forget to add your dependencies into the module.

Module


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import {userDataService} from './userDataService';
import {dateFormatPipe} from './pipes'

@NgModule({
  declarations: [
    AppComponent,dateFormatPipe
  ],
  imports: [
    BrowserModule,
  ],
  providers: [userDataService],
  bootstrap: [AppComponent]
})
export class AppModule { }

We are done, you can inject the service file and reuse it anywhere in the application. In this article we have discussed about filtering a date and appending the local time zone along with that.

Angular 2(+)Angular4/5Date FilteringLocal time zone

Related Info

1. How to show a date is today or yesterday or last week etc using pipe - Angular

2. Communicate with parent and child component in Angular.

3. Angular client side pagination.

4. Angular show more/less pagination

Get Local time zone using JavaScript

It is very important to handle date as different countries are in different time zone. Let us check how we can get local time zone. Our output will be EST, PDT, and EDT etc depending on your time zone. You can test this by updating your time zone in your system.

web


var _timezone = null;
function getLocalTimeZone(dateInput)
{
  if ( _timezone ) return _timezone;
  
  var dateObject = dateInput || new Date(),
  
  dateString = dateObject + "",
  
  _timeZoneAbbr = (
    dateString.match(/\(([^\)]+)\)$/) ||
    dateString.match(/([A-Z]+) [\d]{4}$/)
  );
  
  if ( _timeZoneAbbr ) {
    _timeZoneAbbr = _timeZoneAbbr[1].match(/[A-Z]/g).join("");
  }
 
  if (!_timeZoneAbbr && /(GMT\W*\d{4})/.test(dateString)) {
   return RegExp.$1;
 }
 
 
 _timezone = _timeZoneAbbr;
 
 return _timeZoneAbbr;

};

Run the method getLocalTimeZone() and see the result. I have written about date filtering and formatting using angular js 1 and angular 2+ concept as well, if you are using any of this update that code to include this as well for better use case.

Related Info

1. How to show a date is today or yesterday or last week etc using pipe - Angular

2. Disable submit button until all mandatory fields are filled - Angular

3. Angular client side pagination.

4. Angular show more/less pagination

Tuesday, 17 October 2017

Share data between parent and child component - Angular

Angularparent/childComponent

In this article we will be discussing about communicating between child and parent component in Angular. $scope and $rootScope concepts are removed in Angular, and this is one of the reason for improved performance in Angular application.

1. Share data from parent to child component.
2. Share data from child to parent component.
3. Invoke a function in the parent component from child component.
4. Invoke a function in the child component from parent component.

Let us create a parent and child component first.

Parent component


import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  title : string;
  constructor(){
    this.title = 'Parent child communication';
  }
}

./app.component.html


<child-component></child-component>

Child component


import { Component} from '@angular/core';

@Component({
  selector: 'child-component',
  template: '<div>'
      +'<span>Child Component: </span>'
    +'</div>',
  styleUrls: ['./app.component.css']
})
export class ChildComponent {
 constructor(){}
}

Module code


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import {ChildComponent} from './childComponent';

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

We are done with our simple parent and child component. Now let us check how we can communicate with each other. Let us check the scenarios one by one.

1. Share data from parent to child component


Let us check with a simple example.

Updated parent component html


<child-component name="Angular"></child-component>

Updated child component to receive data


import { Component,Input } from '@angular/core';

@Component({
  selector: 'child-component',
  template: '<div>'
      +'<span>Child Component: </span>'
      +'<span>{{name}}</span>'
    +'</div>',
  styleUrls: ['./app.component.css']
})
export class ChildComponent {
 @Input() name: string;
 constructor(){}
}

Here we have used @Input and the same we have imported as dependency as well. Above example we are passing a string directly, you can assign that into your component and pass as well. For that there will be small change, check below code for that.


Binding a variable in the parent scope

<child-component [name]="name"></child-component>
//name you can declare in your parent component
//same for array and object as well

Binding a string in the parent scope

<child-component name="Angular"></child-component>

Same way you can pass array or object as well. If you want to check with another example check this link as well, here basically explaining about a reusable component but using same concept.

2. Share data from child to parent component.


Above we have explained about sharing data from parent to child component, now let us check how we can share data from child to parent.

Child component


import { Component,Input,Output,EventEmitter  } from '@angular/core';

@Component({
  selector: 'child-component',
  template: '<div>'
      +'<span>Child Component: </span>'
      +'<span>{{name}}</span>'
      +'<button (click)="shareData()">Share data to parent</button>'
    +'</div>',
  styleUrls: ['./app.component.css']
})
export class ChildComponent {
 
 @Input() name: string;
 @Output() shareDataToParent = new EventEmitter();
 
 title : string;
 constructor(){
     this.title = 'Sharing from child to parent';
 }
 
 shareData(){
     this.shareDataToParent.emit(this.title);
 }
}

Dont forget to import Output and EventEmitter. Here we are emitting the data and this should be passed to our parent component, for that check below updated parent component html.


<child-component name="Angular" (shareDataToParent) = shareDataToParent($event)>
</child-component>

You can access this shareDataToParent method in your parent component.

Parent component


shareDataToParent(sharedText:string){
  console.log(sharedText);
}

We are done, click on the button you can see the data printing in the console. I have created a simple rating star component using the same concept, check that as well for better understanding the real time usage.

3. Invoke a function in the parent component from child component.


Basically you can use the same approach what we discussed above to access parent methods. Another approach is to inject the parent component in the child one, but I suggest to use above mentioned approach. So I am not repeating the same here.

4. Invoke a function in the child component from parent component.


Let us check how we can invoke a method in the child component from parent. Here we don’t required any changes in parent component except we need to update html code. Check below updated code.

Updated html code


<child-component #invokeChild></child-component>
<button (click)="invokeChild.invokeChildMethod()">Access child method</button>

Updated child component


invokeChildMethod(){
     console.log('Click triggered from parent component');
 }

Here also no changes except we just added the same method. Click on the button in the parent component you can see your child component method is getting triggered.

And also you can communicate between components using a service file as well, check that as well for better idea. And there are other 7 method to share data between components. In this article we have discussed about communicating between parent and child components also accessing the methods in each component. Hope you enjoyed this article.

Angular 2(+)Angular 4/5parent/childComponent

Related Info

1. How to show a date is today or yesterday or last week etc using pipe - Angular

2. Disable submit button until all mandatory fields are filled - Angular

3. Angular client side pagination.

4. Angular show more/less pagination

Monday, 16 October 2017

Reusable rating star component using angular

AngularRatingRating star component

In this article I will be discussing about implementing a simple rating star component. This component can be reused very easily. Let us check with a working example.


<rating-star max = 10 (onRating) = onRating($event)></rating-star>

Above is the simple representation of a rating star component, this you can add any where in your application. Now let us check the component code. Here by using onRating method you can get the selected rating count.

Rating star Component


<div>
  <span class="icon" *ngFor="let s of maxItem">
    <i [ngClass]=" s <= this.ratedCount ? 'filled' :'' "
       class="fa fa-star"
       aria-hidden="true" (click)="toggleRating(s)"></i>
  </span>
</div>


import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';

@Component({
  selector: 'rating-star',
  templateUrl: './rating-star.component.html',
  styleUrls: ['./rating-star.component.scss']
})
export class RatingStarComponent implements OnInit {

  @Input() max: number;
  @Output() onRating = new EventEmitter<number>();

  public maxItem: any[];
  public ratedCount: number;

  constructor() {
    this.ratedCount = 0;
  }

  ngOnInit() {
    this.maxItem = [];
    for (let i = 0; i < this.max; i++) {
      this.maxItem.push(i + 1);
    }
  }

  public toggleRating(s: number): void {
    this.ratedCount = s;
    this.onRating.emit(this.ratedCount);
  }

}

Parent component

Here you can get the selected rating count. Check below code.


import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  public title : string;

  constructor(){
    this.title = 'Rating stars using Angular';
  }

  public onRating(rating : number): void {
    console.log(rating);
  }
}

Advantage of using this way is that you can reuse this component any where in your application. Using onRating output emitter you can get the selected start count. If you want to use this logic also inside the rating start component then remove this output emitter and use this method directly inside the rating star component.

I will share my css code as well, basically for coloring the star and some look and feel. Here I have used fontawesome icons, you can replace with any icon.

css


.icon{
    display:inline-block;
    margin-right:3px;
    cursor:pointer;
    color:#ccc;
}
.icon:hover{color:#006dcc;}
.filled {color:#006dcc;}

And we are done. You need to import this component in your module for to work everywhere. My suggestion is to keep in your shared module so that you can use this across your application. check below module code.

Module


import {ModuleWithProviders, NgModule} from '@angular/core';
import { CommonModule } from '@angular/common';
import {RatingStarComponent} from './components/rating-star/rating-star.component';

@NgModule({
  declarations: [RatingStarComponent],
  imports: [
    CommonModule
  ],
  exports: [RatingStarComponent]
})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: []
    };
  }
}

Demo

Set initial rating value


If you want to set initial rating you can update the code like below.


<rating-star setRating = 2 max = 10 (onRating) = onRating($event)></rating-star>

Here we are setting initial rating as 2. Update our rating component as well.


//add input
 @Input() setRating : number;
 
  //set in our ngOnInit methode
  ngOnInit(){
     this.ratedCount = this.setRating;
    //etc 
 }

If you want to know more about reusable component refer this link. In this article we have discussed about creating a simple rating star component using Angular.

AngularRatingRating star component

Related Info

1. How to show a date is today or yesterday or last week etc using pipe - Angular

2. Disable submit button until all mandatory fields are filled - Angular

3. Angular client side pagination.

4. Angular show more/less pagination

Friday, 13 October 2017

How to show a date is today or yesterday or last week etc using pipe - Angular

Angular 2(+)Angular4/5Date FilteringDate FormattingNice date

Let us check how we can convert a timestamp/date to today or last week etc using a simple angular pipe. This will be very help full for users to understand the time very clearly. We can achieve this by using a simple pipe.

Let us create a simple pipe and a method for converting date into user readable format.

Pipe


@Pipe({
    name: 'niceDateFormatPipe',
})
export class niceDateFormatPipe implements PipeTransform {
    transform(value: string) {
       
       var _value = Number(value);
       
       var dif = Math.floor( ( (Date.now() - _value) / 1000 ) / 86400 );
       
       if ( dif < 30 ){
            return convertToNiceDate(value);
       }else{
           var datePipe = new DatePipe("en-US");
           value = datePipe.transform(value, 'MMM-dd-yyyy');
           return value;
       }
    }
}

function convertToNiceDate(time: string) {
    var date = new Date(time),
        diff = (((new Date()).getTime() - date.getTime()) / 1000),
        daydiff = Math.floor(diff / 86400);

    if (isNaN(daydiff) || daydiff < 0 || daydiff >= 31)
        return '';

    return daydiff == 0 && (
        diff < 60 && "Just now" ||
        diff < 120 && "1 minute ago" ||
        diff < 3600 && Math.floor(diff / 60) + " minutes ago" ||
        diff < 7200 && "1 hour ago" ||
        diff < 86400 && Math.floor(diff / 3600) + " hours ago") ||
        daydiff == 1 && "Yesterday" ||
        daydiff < 7 && daydiff + " days ago" ||
        daydiff < 31 && Math.ceil(daydiff / 7) + " week(s) ago";
}

Html


<p>{{currentTime | niceDateFormatPipe }}</p>

We are done. I will share module code as well. Here I will be importing our new pipe.

Module


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { DatePipe } from '@angular/common';
import {niceDateFormatPipe} from './pipes'

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

You can update the pipe for getting any other date format. For more example of date formatting in angular refere this post. In this article we have discussed about converting a date into a more readable format by using a simple angular pipe.

Angular 2(+)Angular4/5Date FilteringDate FormattingNice date

Related Info

1. Share data between components using a service file.

2. Disable submit button until all mandatory fields are filled - Angular

3. Angular client side pagination.

4. Angular show more/less pagination

Tuesday, 10 October 2017

Disable submit button until all mandatory fields are filled - Angular

Let us check how we can disable submit button of a form until all mandatory fields are filled. Angular folks made these things very simple, before explaining those you can check this link to know how it was in Angular js 1. Let us create a simple form first.


<form (ngSubmit)="onSubmit()">

  <div class="form-group">
    <label for="firstname">First Name</label>
    <input type="text" class="form-control" id="firstname" 
      required [(ngModel)]="firstname" name="firstname">
  </div>

  <div class="form-group">
   <label for="lastname">Last Name</label>
   <input type="text"  class="form-control" id="lastname" 
     [(ngModel)] = "lastname" name="lastname">
  </div>

  <button type="submit">Submit</button>

</form>


Above one is a simple form which has first name and last name and first name we made as mandatory by adding required type. Now see below code which will disable the submit button until mandatory field are filled.


<form (ngSubmit)="onSubmit()" #myForm="ngForm">

  <div class="form-group">
    <label for="firstname">First Name</label>
    <input type="text" class="form-control" id="firstname" 
      required [(ngModel)]="firstname" name="firstname">
  </div>

  <div class="form-group">
   <label for="lastname">Last Name</label>
   <input type="text"  class="form-control" id="lastname" 
     [(ngModel)] = "lastname" name="lastname">
  </div>

  <button type="submit" [disabled]="!myForm.form.valid">Submit</button>

</form>

Here we have added #myForm="ngForm" to form body and also added [disabled]="!myForm.form.valid" to submit button. Our job is over, angular made us everything easy. Now let us check with some more example. Let us add max length and min length.


<div class="form-group">
 <label for="lastname">Last Name</label>
 <input type="text"  class="form-control" id="lastname" 
   required minlength = '2' maxlength="6" [(ngModel)] = "lastname" name="lastname">
</div>

Now let us check with pattern validation, it was ng-pattern in Angular js 1 here is is just pattern.


<div class="form-group">
  <label for="mobnumber">Mob Number</label>
  <input type="text"  class="form-control" id="mobnumber"  minlength = '2' 
  maxlength="10" pattern="^[0-9()\-+\s]+$" [(ngModel)] = "mobnumber" name="mobnumber">
</div>

Basically you don’t need to worry about validation, angular will take care for you.

Full example


<form (ngSubmit)="onSubmit()" #myForm="ngForm">

 <div class="form-group">
  <label for="firstname">First Name</label>
  <input type="text" class="form-control" id="firstname" 
   required [(ngModel)]="firstname" name="firstname">
 </div>

 <div class="form-group">
  <label for="middlename">Middle Name</label>
  <input type="text"  class="form-control" id="middlename" 
   [(ngModel)]="middlename" name="middlename">
 </div>

 <div class="form-group">
  <label for="lastname">Last Name</label>
  <input type="text"  class="form-control" id="lastname" 
   required minlength = '2' maxlength="6" [(ngModel)] = "lastname" name="lastname">
 </div>

 <div class="form-group">
  <label for="mobnumber">Mob Number</label>
  <input type="text"  class="form-control" id="mobnumber"  
   minlength = '2' maxlength="10" pattern="^[0-9()\-+\s]+$" 
   [(ngModel)] = "mobnumber" name="mobnumber">
 </div>

 <button type="submit" [disabled]="!myForm.form.valid">Submit</button>

</form>

Update the plunker and test your changes.

Dont forgot to import form module.


import { FormsModule } from '@angular/forms';

In this article we have discussed about form validation, basically disabling submit button until all mandatory fields are filled.

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