Angular Source Code
Last active
March 1, 2020 10:16
-
-
Save gopalakrishnan-subramani/714aab26b87f2e79a87905f241ada11c to your computer and use it in GitHub Desktop.
Angular
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, OnInit } from '@angular/core'; | |
import { DomSanitizer } from '@angular/platform-browser'; | |
@Component({ | |
selector: 'app-about', | |
templateUrl: './about.component.html', | |
styleUrls: ['./about.component.scss'] | |
}) | |
export class AboutComponent implements OnInit { | |
html=`<div> | |
<h1>Angular Router</h1> | |
</div>`; | |
safeHtml: any; | |
constructor(private sanitizer:DomSanitizer) { } | |
ngOnInit() { | |
this.safeHtml = this.sanitizer.bypassSecurityTrustHtml(this.html); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// auth-interceptor.service.ts | |
import { Injectable, Injector } from '@angular/core'; | |
// ng 4.3 | |
import { HttpInterceptor, | |
HttpRequest, | |
HttpHandler, | |
HttpEvent } from '@angular/common/http'; | |
import { Observable } from 'rxjs'; | |
import { AuthService } from '../shared/services/auth.service'; | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class AuthInterceptorService implements HttpInterceptor { | |
constructor(private authService: AuthService) { | |
console.log('Interceptor created'); | |
} | |
intercept(request: HttpRequest<any>, | |
next: HttpHandler): Observable<HttpEvent<any>> { | |
console.log ('Intercepter ', request.url, request.method); | |
//example only | |
console.log('token ', this.authService.getToken()); | |
if (this.authService.authenticated) { | |
request = request.clone({ | |
setHeaders: { | |
Authorization: `JWT ${this.authService.getToken()}` | |
} | |
}); | |
} | |
return next.handle(request); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// auth.guard.ts | |
import { AuthService } from './../services/auth.service'; | |
import { Injectable } from '@angular/core'; | |
import { CanActivate, | |
ActivatedRouteSnapshot, | |
RouterStateSnapshot, | |
Router} from '@angular/router'; | |
import { Observable } from 'rxjs'; | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class AuthGuard implements CanActivate { | |
constructor(private authService: AuthService, | |
private router: Router) { | |
} | |
canActivate( | |
next: ActivatedRouteSnapshot, | |
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean { | |
if (this.authService.authenticated) { | |
return true; | |
} | |
this.router.navigateByUrl('/auth/login'); | |
return false; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class Brand { | |
id: number; | |
name: string; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<h1>Checkout Details</h1> | |
<form [formGroup]="form" > | |
<p> | |
<label>Full Name:</label> | |
<input type="text" formControlName="fullName" > | |
</p> | |
<p> | |
<label>State:</label> | |
<select formControlName="state" > | |
<option [value]='state.id' *ngFor="let state of states$ | async">{{state.name}}</option> | |
</select> | |
</p> | |
<p> | |
<label>City:</label> | |
<select formControlName="city" > | |
<option [value]='city.id' *ngFor="let city of cities$ | async"> | |
{{city.name}}</option> | |
</select> | |
</p> | |
<p> | |
<label>Country</label> | |
<input type="text" formControlName="country" > | |
IN or India | |
</p> | |
<p> | |
<button type="submit" [disabled]="!form.valid">Submit</button> | |
</p> | |
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Observable } from 'rxjs'; | |
import { HttpClient } from '@angular/common/http'; | |
import {Component, OnInit, Inject, Attribute} from "@angular/core"; | |
import {ActivatedRoute, Params} from "@angular/router"; | |
import { FormGroup, FormControl, Validators, | |
FormBuilder, Validator, AbstractControl } | |
from '@angular/forms'; | |
import { environment } from 'src/environments/environment'; | |
function CountryValidator(control: AbstractControl): { | |
[key: string]: boolean; | |
} { | |
console.log("Console ", control.value); | |
if (control.value === 'IN' || control.value === 'India') { | |
return; // return undefined means no error | |
} | |
return { | |
invalidCountry: true | |
}; | |
} | |
interface State { | |
code: string; | |
id: number; | |
name: string; | |
} | |
interface City { | |
code: string; | |
id: number; | |
name: string; | |
stateId: number; | |
} | |
import {filter, map} from 'rxjs/operators'; | |
@Component({ | |
selector: 'app-checkout', | |
templateUrl: './checkout.component.html', | |
styleUrls: ['./checkout.component.scss'] | |
}) | |
export class CheckoutComponent implements OnInit { | |
states$: Observable<State[]>; | |
cities$: Observable<City[]>; | |
form: FormGroup; | |
fullNameControl:FormControl; | |
stateControl:FormControl; | |
cityControl:FormControl; | |
countryControl:FormControl; | |
constructor( | |
private route: ActivatedRoute, | |
private http: HttpClient, | |
formBuilder: FormBuilder | |
) { | |
this.fullNameControl = new FormControl("", Validators.required); | |
this.stateControl = new FormControl(""); | |
this.cityControl = new FormControl(""); | |
this.countryControl = new FormControl("", CountryValidator); | |
this.form = formBuilder.group({ | |
"fullName": this.fullNameControl, | |
"state": this.stateControl, | |
"city": this.cityControl, | |
"country": this.countryControl | |
}); | |
} | |
ngOnInit() { | |
this.states$ = this.http.get<State[]>(`${environment.apiEndPoint}/api/states`); | |
this.stateControl.valueChanges | |
.pipe(filter ( (value:any) => !!value)) | |
.subscribe ( (value: any) => { | |
this.cities$ = this.http.get<City[]>(`${environment.apiEndPoint}/api/cities?stateId=${value}`); | |
}); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { HttpClient } from '@angular/common/http'; | |
import { Injectable, Inject, ErrorHandler } from "@angular/core"; | |
import {Location} from "@angular/common"; | |
import {Router} from "@angular/router"; | |
import { environment } from '../../environments/environment'; | |
// goes into providers section of app.module.ts | |
/* | |
{ | |
provide: ErrorHandler, | |
useClass: ErrorHandlerService | |
}, | |
*/ | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class ErrorHandlerService implements ErrorHandler { | |
constructor(private location: Location, | |
private http: HttpClient ) { | |
} | |
public handleError( error: any ) : void { | |
// Log to the console. | |
try { | |
console.log("Custom error handler"); | |
console.group( "ErrorHandler" ); | |
console.error( error.message ); | |
console.error( error.stack ); | |
console.groupEnd(); | |
this.http.post(`${environment.apiEndPoint}/logs/errors`, | |
{ | |
message: error.message, | |
trace: error.stack | |
}) | |
.subscribe( (savedError) => { | |
console.log('error saved successfully') | |
}, (err: any) => { | |
console.log('error while posting errors to server ', err) | |
}) | |
} catch ( handlingError ) { | |
console.group( "ErrorHandler" ); | |
console.warn( "Error when trying to output error." ); | |
console.error( handlingError ); | |
console.groupEnd(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ng g pipe shared/pipes/filter.pipe.ts | |
// shared/pipes/filter.pipe.ts | |
import { Pipe, PipeTransform } from '@angular/core'; | |
// {{ dataItems | filter:'year':'<':2010}} | |
@Pipe({ | |
name: 'filter' | |
}) | |
export class FilterPipe implements PipeTransform { | |
transform(items: any[], | |
field: string, | |
predicate: string, | |
value: any): any[] { | |
if (!items || !field || !predicate || !value) { | |
return items; | |
} | |
if (predicate == '>') { | |
// return items.filter(item => item[field] > value) | |
return items.filter(function(item: any):boolean { | |
return item[field] > value | |
}) | |
} | |
if (predicate == '<') { | |
return items.filter(item => item[field] < value) | |
} | |
if (predicate == '==') { | |
return items.filter(item => item[field] == value) | |
} | |
return items; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//shared/directives/highlight.directive.ts | |
// ng g directive shared/directives/highlight | |
import { Directive, | |
OnInit, | |
OnDestroy, | |
Input, | |
Output, | |
EventEmitter, | |
HostListener, | |
ElementRef, | |
Renderer2 | |
} from '@angular/core'; | |
@Directive({ | |
// [] must | |
selector: '[appHighlight]', | |
exportAs: 'appHighlight' | |
}) | |
export class HighlightDirective implements OnInit, OnDestroy { | |
// appHighlight="lightgreen" | |
@Input("appHighlight") | |
color: string; | |
@Output("appHighlightChange") | |
colorChange: EventEmitter<string> = new EventEmitter(); | |
constructor(private hostElement: ElementRef, | |
private renderer: Renderer2) { | |
console.log("Highlight directive created"); | |
} | |
ngOnInit() { | |
console.log("highlight init"); | |
console.log("Color ", this.color); | |
} | |
ngOnDestroy() { | |
console.log("highlight destroy"); | |
} | |
@HostListener('click') | |
onClick() { | |
console.log("Directive click"); | |
this.colorChange.emit("red"); | |
} | |
@HostListener('mouseenter') | |
onEnter() { | |
this.renderer | |
.setStyle(this.hostElement.nativeElement, | |
'background', | |
this.color); | |
} | |
@HostListener('mouseleave') | |
onLeave() { | |
this.renderer | |
.removeStyle(this.hostElement.nativeElement, | |
'background'); | |
} | |
setColor(color: string) { | |
console.log('set color ', color); | |
this.color = color; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<h2>Product List</h2> | |
<table> | |
<tr> | |
<th>Name</th> | |
<th>Price</th> | |
<th>Year</th> | |
<th>+Cart</th> | |
</tr> | |
<tr *ngFor="let product of (products$ | async) "> | |
<td> | |
<a [routerLink]="['/products', 'edit', product.id, {source:'list'}]" > | |
{{product.name}} | |
</a> | |
</td> | |
<td>{{product.price}}</td> | |
<td>{{product.year}}</td> | |
<td> | |
<button (click)="addToCart(product)">+Cart</button> | |
</td> | |
</tr> | |
</table> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///product/services/product.service.ts | |
import { environment } | |
from './../../../environments/environment'; | |
import { Product } from './../models/product'; | |
import { Brand } from './../models/brand'; | |
import { Observable } from 'rxjs'; | |
import { Injectable } from '@angular/core'; | |
import { HttpClient } from '@angular/common/http'; | |
console.log("ENV ", environment) | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class ProductService { | |
constructor(private http: HttpClient) { } | |
// GET /api/products | |
getProducts(): Observable<Product[]> { | |
//FIXME: implement get api for products | |
return this.http | |
.get<Product[]>(`${environment.apiEndPoint}/api/products`); | |
} | |
// GET /api/products | |
searchProducts(q: string): Observable<Product[]> { | |
return this.http.get<Product[]>(`${environment.apiEndPoint}/api/products?q=${q}`); | |
} | |
// GET /api/products/100 | |
getProduct(id: any): Observable<Product> { | |
return this.http | |
.get<Product>(`${environment.apiEndPoint}/api/products/${id}`); | |
} | |
// Cache | |
// Option 1. In memory JS [on refresh, removed] | |
// Option 2: browser storage: sessionStorage, per tab based, works on refresh | |
// closing tab, remove the sessionStorage | |
// Option 3: browser storage: localStorage: persistent, | |
// remains active on closing browser, shutdown system | |
storage: Storage = window.localStorage; | |
// GET /api/brands | |
getBrands(): Observable<Brand[]> { | |
//todo: check if cache present, serve from cache | |
// let brandsJson = this.storage.getItem("brands"); | |
// if (brandsJson) { | |
// console.log("Serving brands from cache "); | |
// //TODO: convert to observable | |
// let brands: Brand[] = <Brand[]> JSON.parse(brandsJson); | |
// return Observable.of(brands); | |
// } | |
console.log("Serving from server"); | |
return this.http | |
.get<Brand[]>(`${environment.apiEndPoint}/api/brands`) | |
} | |
// update existing product | |
// PUT /api/products/12345 | |
// {{product json data}} | |
// response | |
// updated product data | |
// to create new product | |
// POST /api/products | |
// {{product json data without id}} | |
// response | |
// updated product data with id | |
saveProduct(product: Product):Observable<Product> { | |
if (product.id) { // update | |
return this.http | |
.put<Product>(`${environment.apiEndPoint}/api/products/${product.id}`, | |
product); | |
} else { //create | |
return this.http | |
.post<Product>(`${environment.apiEndPoint}/api/products`, | |
product); | |
} | |
} | |
deleteProduct(id: number): Observable<any> { | |
return this.http | |
.delete(`${environment.apiEndPoint}/api/products/${id}`) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class Product { | |
id: number; | |
name: string; | |
price: number; | |
year: number; | |
brandId: number; // reference to brand model | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// resolver | |
import { ProductService } from './../services/product.service'; | |
import { Injectable } from '@angular/core'; | |
import { Product } from '../models/product'; | |
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; | |
import { Observable } from 'rxjs'; | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class ProductsResolveService implements Resolve<Product[]> { | |
constructor(private productService: ProductService) { } | |
resolve( | |
route: ActivatedRouteSnapshot, | |
state: RouterStateSnapshot | |
): Observable<any>|Promise<any>|any { | |
return this.productService.getProducts(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { CanDeactivate } from '@angular/router'; | |
import { Observable } from 'rxjs'; | |
import { Editable } from '../models/editable'; | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class SaveAlertGuard implements CanDeactivate<Editable> { | |
canDeactivate(target: Editable) { | |
if (target.isSaved()) | |
return true; | |
return window.confirm("Unsaved changes, continue?") | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ng g pipe shared/pipes/sort.pipe.ts | |
//shared/pipes/sort.pipe.ts | |
import { Pipe, PipeTransform } from '@angular/core'; | |
@Pipe({ | |
name: 'sort', | |
pure: false // by default is true | |
}) | |
export class SortPipe implements PipeTransform { | |
// stateful pipe | |
sortedItems: any[]; | |
actualItems: any[]; | |
// transform is called all times if pure is set to false | |
// transform is called | |
// whenever object changed if pure set to true | |
transform(items: any[], | |
fieldName: string, | |
order: string = 'asc'): any { | |
console.log('sort pipe transform called', items, fieldName) | |
if (!items || !fieldName) { | |
return items; | |
} | |
if (items !== this.actualItems) { | |
this.actualItems = items; | |
} // FIXME | |
console.log('in sort', order); | |
if (order === 'desc') { | |
return items.sort ( (left, right) => { | |
// console.log(left, right); | |
if (left[fieldName] < right[fieldName]) | |
return 1; | |
if (left[fieldName] > right[fieldName]) | |
return -1; | |
return 0; | |
}) | |
} | |
//FIXME: | |
// desc | |
return items.sort ( (left, right) => { | |
console.log(left, right); | |
if (left[fieldName] < right[fieldName]) | |
return -1; | |
if (left[fieldName] > right[fieldName]) | |
return 1; | |
return 0; | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment