Angular 5 interceptor for loading message

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { UserDetailsComponent } from './user-details/user-details.component';

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { CommentsComponent } from './comments/comments.component';
import { loadingInterceptor } from './Services/loadingInterceptor';

@NgModule({
  declarations: [
    AppComponent,
    UserDetailsComponent,
    CommentsComponent
  ],
  imports: [
    BrowserModule,HttpClientModule
  ],
  providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: loadingInterceptor,
    multi: true
}],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html

<div class="row">
<div class="col-md-6">
    <app-user-details></app-user-details></div>
<div class="col-md-6">
    <app-comments></app-comments></div>
</div>
<div class="loading" style="display: none">
  <span>Loading.....</span></div>

app.component.css


.loading {
    background: rgba(0,0,0,0.4);
    position: fixed;
    display: block;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

.loading span {
    position: fixed;
    left: 50%;
    top: 50%;
    border: solid 1px #ccc;
    display: block;
    padding: 20px 40px;
    margin-left: -40px;
    background: rgba(255,255,255,0.8);
}

comments/comments.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { AppComponent } from '../app.component';

@Component({
  selector: 'app-comments',
  templateUrl: './comments.component.html',
  styleUrls: ['./comments.component.css']
})
export class CommentsComponent implements OnInit {
  commentList: Array<Comment>;
  constructor(private httpClient: HttpClient) { }

  ngOnInit() {
  }
  getComments() {
    this.commentList = [];
    this.httpClient.get('https://jsonplaceholder.typicode.com/comments').subscribe((data: Array<Comment>) => {
      this.commentList = data;
    })
  }
}

export class Comment {
  public body: string;
  public email: string;
  public id: number;
  public name: string;
  public postId: number;
}

comments/comments.component.html

<div class="row">
<div class="col-md-12">
    <button (click)="getComments()" class="btn btn-primary">Get Comments</button></div>
<div class="col-md-12" *ngFor="let item of commentList" style="max-height:500px;">
    <b style="display:block">{{item.name}}</b>
    <small>{{item.email}}</small>

{{item.body}}</div>
</div>

user-details/user-details.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-user-details',
  templateUrl: './user-details.component.html',
  styleUrls: ['./user-details.component.css']
})
export class UserDetailsComponent implements OnInit {

  private user: User;
  constructor(private httpClient: HttpClient) { }

  ngOnInit() {
  }
  getUserInfo() {
    this.httpClient.get('https://jsonplaceholder.typicode.com/users/3').subscribe(
      success => {
        this.user = (success as User);
      }
    )

  }
}

export class User {

  public id: number;
  public name: string;
  public username: string;
  public email: string;
  public phone: string;

}

user-details/user-details.component.html

<div class="row col-md-12">
  <button (click)="getUserInfo()" class="btn">Get User Info</button></div>
<div class="row col-md-12" *ngIf="user">
<table class="table">
<tr>
<td>Name</td>
<td>{{user.name}}</td>
</tr>
<tr>
<td>User Name</td>
<td>{{user.username}}</td>
</tr>
<tr>
<td>Email</td>
<td>{{user.email}}</td>
</tr>
<tr>
<td>Phone</td>
<td>{{user.phone}}</td>
</tr>
</table>
</div>

services/loadingInterceptor.ts

import { Injectable, Injector } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/observable/throw'
import 'rxjs/add/operator/catch';

@Injectable()
export class loadingInterceptor implements HttpInterceptor {
    constructor() { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        let loadingContainer: HTMLElement = document.getElementsByClassName('loading').item(0) as HTMLElement;
        loadingContainer.style.display = 'block';
        //send the request
        next.handle(req).subscribe((observer: any) => {
            if (observer.status == 200) {
                loadingContainer.style.display = 'none';
            }
        })
        return next.handle(req);
    }
}
Advertisements

Month picker in Angular 2

 


I am still improving this one. Updates will come soon.

import { Component, OnInit, Input, OnChanges, ElementRef, Output, EventEmitter, HostListener } from '@angular/core';<span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>

@Component({
    moduleId: module.id,
    selector: 'fdms-month-picker',
    templateUrl: 'monthPicker.html'
})
export class monthPickerDirective implements OnInit, OnChanges {
    @Input() model: string|Date;
    @Input() config: ImonthPickerConfig;
    @Output() modelChange  = new EventEmitter();
    __monthPicker: monthPicker;
    constructor(private _elementRef: ElementRef) {
        this.__monthPicker = new monthPicker();
    }
    ngOnInit() {
    }
    ngOnChanges(changes:any) {
        if (this.model) {
            this.__monthPicker.setCurrentdate(new Date(this.model));
        }
    }

    onCalendarIconClick() {
        this.switchToMonthMode();
        this.__monthPicker.setCurrentdate(this.model ? new Date(this.model):new Date());
        this.__monthPicker.toggleState();
    }
    switchToYearMode() {
        this.__monthPicker.viewMode = 'y';
        this.__monthPicker.fillYearsInSelectionList();
    }
    switchToMonthMode() {
        this.__monthPicker.viewMode = 'm';
        this.__monthPicker.fillMonthsInSelectionList();
    }
    onselectionItemClick(item: IDatePickerSelectionItem) {
        if (item.type == 'y') {
            this.__monthPicker.displayYear = item.value;
            this.switchToMonthMode();
        } else if (item.type == 'm') {
            this.onSelectMonth(item);
        }
    }
    onSelectMonth(item: IDatePickerSelectionItem) {
        this.__monthPicker.displayMonth = item.text;
        this.__monthPicker.displayMonthIndex = item.value;

        this.__monthPicker.selectedMonth = item.text;
        this.__monthPicker.selectedMonthIndex = item.value;
        this.__monthPicker.selectedYear = this.__monthPicker.displayYear;

        this.model = (this.__monthPicker.selectedMonthIndex + 1) + "/01/" + this.__monthPicker.selectedYear;
        //this.model = new Date(this.__monthPicker.selectedYear, this.__monthPicker.selectedMonthIndex, 1);
        this.__monthPicker.state = "closed";
        this.modelChange.next(this.model);
    }

    onPrevYearSelection() {
        this.__monthPicker.displayYear--;
        if (this.__monthPicker.viewMode == 'y') { this.__monthPicker.fillYearsInSelectionList(); }
    }
    onNextYearSelection() {
        this.__monthPicker.displayYear++;
        if (this.__monthPicker.viewMode == 'y') { this.__monthPicker.fillYearsInSelectionList(); }
    }

    onCancel() {
        this.__monthPicker.state = "closed";
    }

    @HostListener('document:click', ['$event', '$event.target'])
    public onClick(event: MouseEvent, targetElement: HTMLElement): void {
        if (!targetElement) {
            return;
        }

        const clickedInside = this._elementRef.nativeElement.contains(targetElement);
        if (!clickedInside) {
            this.__monthPicker.state = "closed";
        }
    }
}
export interface ImonthPickerConfig {
    readonly?: boolean;
    cssClass?: string;
    placeHolder?: string;
}
export interface IDatePickerSelectionItem {
    text: string;
    value: number;
    type: string;
}
class monthPicker {
    state: string;
    selectionItems: Array<IDatePickerSelectionItem>;
    selectedMonth: string;
    selectedMonthIndex: number;
    selectedYear: number;
    displayMonth: string;
    displayMonthIndex: number;
    displayYear: number;
    viewMode: string;
    private months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    constructor() {
        this.state = "closed";
        this.viewMode = 'm';
        this.fillMonthsInSelectionList();
        let currentDate = new Date();
        this.setCurrentdate(currentDate);
    }
    toggleState() {
        this.state = this.state == "closed" ? "open" : "closed";
    }

    fillMonthsInSelectionList() {
        this.selectionItems = [];
        this.months.forEach((v: string, i: number) => this.selectionItems.push({ text: v, value: i, type: 'm' }));
    }
    fillYearsInSelectionList() {
        this.selectionItems = [];
        for (let start = this.displayYear - 6; start <= this.displayYear + 5; start++) {
            this.selectionItems.push({ text: start.toString(), value: start, type: 'y' });
        }
    }
    setCurrentdate(currentDate: Date)
    {
        this.displayMonth = this.months[(currentDate.getMonth() - 1)];
        this.displayMonthIndex = currentDate.getMonth();
        this.displayYear = currentDate.getFullYear();

        this.selectedMonth = this.displayMonth;
        this.selectedMonthIndex = this.displayMonthIndex;
        this.selectedYear = this.displayYear;
    }
}

HTML Template

<div class="input-group fdms-mp-input">
    <input type="text" readonly value="{{model|date: 'MM/yyyy'}}" class="form-control" placeholder="{{config.placeHolder}}" />
    <span class="input-group-addon" (click)="onCalendarIconClick()"><i class="fa fa-calendar"></i></span>
<div class="fdms-month-picker" *ngIf="__monthPicker.state=='open'">
<div class="col-md-12 d-title">{{__monthPicker.selectedMonth}}, {{__monthPicker.selectedYear}}</div>
<div class="col-md-12 d-nav">
<div class="col-md-3"><span (click)="onPrevYearSelection()"><</span></div>
<div class="col-md-6"><span (click)="switchToYearMode()">{{__monthPicker.displayYear}}</span></div>
<div class="col-md-3"><span (click)="onNextYearSelection()">></span></div>
</div>
<div class="col-md-12 d-selection-wraper">
<div class="col-md-3 d-selection-item" *ngFor="let item of __monthPicker.selectionItems">
                <span (click)="onselectionItemClick(item)">{{item.text}}</span></div>
</div>
<div class="col-md-12 d-actions">
            <span class="d-action d-action-cancel" (click)="onCancel()">Cancel</span></div>
</div>
</div>
    .fdms-mp-input .input-group-addon {
    background: #1792e5;
    color: #FFF;
    border: none;
    }
    .fdms-month-picker {
        width: 250px;
        position: absolute;
        background: #FFF;
        right: 0;
        top: 47px;
        z-index: 1010;
        border: solid 1px #2280bf;
    }

    .d-selection-item {
        padding: 0;
    }

    .d-title {
        height: 40px;
        text-align: center;
        background: #1792e5;
        color: #FFF;
        border-bottom: solid 4px #1382ce;
        line-height: 40px;
    }

    .d-nav {
        padding: 2px;
    }

        .d-nav span {
            cursor: pointer;
        }

        .d-nav > .col-md-6 > span {
            display: block;
            text-align: center;
        }

    .d-selection-item {
        height: 40px;
        text-align: center;
        color: #303030;
        cursor: pointer;
    }

    .d-actions {
        /* border-top: solid 1px #1382ce; */
        height: 40px;
    }

    span.d-action.d-action-cancel {
        color: #1792e5;
        line-height: 40px;
        float: right;
        cursor: pointer;
    }

Showing angular expression at page load

angularIn my application I want to show a table data. I am showing a loading icon at first. At that time table will hidden. after data load that table will display. its working good. But some times some browsers showing angular expressions in table at page. After a 1/4 sec it will gone. But it shown 1/4 sec!!. I tried ng-show, ng-if, add a class,etc. everything failed. It is not fixed permanently. After that I tried with ng-cloak. It works!

I added the below code in my css file, and add a class to my table element.

CSS

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}

Html

<table  class="ng-cloak">
....</table>

Angular dataTable multicolumn filter

angularIn my project i got a requirement that client need to search column wise with the default common search. I checked it in google, found column filter in footer row. But I need it in header itself. Based on that example created one.

 

HTML

<!DOCTYPE html>
<html>

  <head>
    		<link rel="stylesheet" href="style/jquery.dataTables.css" />
  </head>

  <body ng-app="datatablesSampleApp">
<div ng-controller="simpleCtrl" class="code"  style="width: 500px">
<table datatable="" dt-options="dtOptions" dt-columns="dtColumns">
<thead>
<tr>
<th>ID
                <input type="text" ng-model="search.id" ng-change="searchData(search.id,0)" ng-click="blockSorting($event)" /></th>
<th>FirstName
                <input type="text" ng-model="search.firstName" ng-change="searchData(search.firstName,1)"  ng-click="blockSorting($event)"/></th>
<th>LastName</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="person in data">
<td>{{ person.id }}</td>
<td>{{ person.firstName }}</td>
<td>{{ person.lastName }}</td>
</tr>
</tbody>
</table>
</div>
<script src="script/jquery-1.10.1.min.js"></script>
    <script src="script/jquery.dataTables.js"></script>
    <script src="http://code.angularjs.org/1.2.15/angular.js"></script>
    <script src="script/angular-resource.js"></script>
    <script  src="angular-datatables.min.js"></script>
    <script src="script.js"></script>
  </body>

</html>

JS

(function (angular) {
    'use strict';
    angular.module('datatablesSampleApp', ['datatables']).
        controller('simpleCtrl', function ($scope, DTOptionsBuilder, DTColumnBuilder) {
            $scope.data = [{
                "id": 860,
                "firstName": "Superman",
                "lastName": "Yoda"
            }, {
                "id": 870,
                "firstName": "Foo",
                "lastName": "Whateveryournameis"
            }, {
                "id": 590,
                "firstName": "Toto",
                "lastName": "Titi"
            }];
            $scope.dtOptions = DTOptionsBuilder.newOptions().withPaginationType('full_numbers');
            $scope.searchData = function (searchText, index) {
                $scope.table.column(index).search(searchText).draw();
            };
            $scope.$on('event:dataTableLoaded', function (event, loadedDT) {
                $scope.table = loadedDT.DataTable;
            });
            $scope.blockSorting = function($event){
                $event.preventDefault();
                $event.stopPropagation();
            }
        });
})(angular);

Output
angular multi column filter

Bind angular scope to dynamically added html

angularSome times we need to integrate html contents to our angular application. some times we create contents from jQuery and integrate it to our application. like kendo UI in jQuery style, jQuery dataTables etc.
At that time the following snippet will useful.

<!DOCTYPE html>
<html lang="en">

<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
</head>

<body ng-app="app">
<div ng-controller="ctrl" id="dvController">
        <test-dir></test-dir>
        <button onclick="addTemplate1()">Add template 1</button>
        <button onclick="addTemplate2()">Add template 2</button>
<div id="dvContainer"></div>
</div>
<script>
                         function addTemplate1() {
                             var template = "<test-dir></test-dir>";
                             $("#dvContainer").html(template);
                             bindAngular();
                         }

                         function addTemplate2() {
                             var template = "FirstName : {{FirstName}}
LastName : {{LastName}}";
                             $("#dvContainer").html(template);
                             bindAngular();
                         }
                         function bindAngular() {
                             var $controllerElement = angular.element('#dvController');
                             var $appElement = angular.element('body');

                             // compiling and applying / digesting the scope.
                             $appElement.injector().invoke(function ($compile) {
                                 var scope = $controllerElement.scope();
                                 $compile($controllerElement)(scope);
                                 scope.$apply();
                             });
                         }
                         angular.module('app', []).controller('ctrl', function ($scope) {
                             $scope.FirstName = "Musthaan";
                             $scope.LastName = "Majeed";
                         }).directive('testDir', function () {
                             return {
                                 template: "
<h1>From dir</h1>
"
                             };
                         })
    </script>
</body>

</html>

Error: [jqLite:nosel] Looking up elements via selectors is not supported by jqLite

One day i am just playing with angular with jQuery. At that time I got an error like

Error: [jqLite:nosel] Looking up elements via selectors is not supported by jqLite
My html looks like,



<head>    

    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>

Because while initializing time angular doesn’t knows that there is jQuery.

Just swap the order and fix this issue.



<head>    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
</head>