├── src
├── app
│ ├── welcome-component
│ │ ├── welcome-component.component.css
│ │ ├── welcome-component.component.html
│ │ └── welcome-component.component.ts
│ ├── app.component.css
│ ├── employee-component
│ │ ├── employee-component.component.css
│ │ ├── employeedetail-component
│ │ │ ├── employeedetail-component.component.css
│ │ │ ├── employeedetail-component.component.html
│ │ │ ├── employeedetail-component.component.ts
│ │ │ └── employeedetail.guard.ts
│ │ ├── employee.ts
│ │ ├── employee-component.component.html
│ │ ├── employee.module.ts
│ │ ├── employee.service.ts
│ │ └── employee-component.component.ts
│ ├── shared
│ │ └── star
│ │ │ ├── star.component.css
│ │ │ ├── star.component.html
│ │ │ └── star.component.ts
│ ├── app.component.ts
│ ├── app.component.html
│ └── app.module.ts
├── styles.css
├── index.html
├── main.ts
└── polyfills.ts
├── tsconfig.json
├── package.json
├── angular.json
└── README.md
/src/app/welcome-component/welcome-component.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | p {
2 | font-family: Lato;
3 | }
--------------------------------------------------------------------------------
/src/app/employee-component/employee-component.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/employee-component/employeedetail-component/employeedetail-component.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/welcome-component/welcome-component.component.html:
--------------------------------------------------------------------------------
1 |
2 | Welcome Works!
3 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | @import '~bootstrap/dist/css/bootstrap.min.css';
2 | @import 'font-awesome/css/font-awesome.min.css';
--------------------------------------------------------------------------------
/src/app/shared/star/star.component.css:
--------------------------------------------------------------------------------
1 | .crop {
2 | overflow: hidden;
3 | }
4 | div {
5 | cursor: pointer;
6 | }
7 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | loading
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/app/employee-component/employee.ts:
--------------------------------------------------------------------------------
1 | export interface IEmployee {
2 | id: number;
3 | code: string;
4 | name: string;
5 | salary: number;
6 | starRating: number;
7 | }
8 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'my-app',
5 | templateUrl: './app.component.html',
6 | styleUrls: ['./app.component.css']
7 | })
8 | export class AppComponent {
9 | pageTitle: string = 'Employee Management';
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/shared/star/star.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/app/employee-component/employeedetail-component/employeedetail-component.component.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
10 |
--------------------------------------------------------------------------------
/src/app/welcome-component/welcome-component.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-welcome-component',
5 | templateUrl: './welcome-component.component.html',
6 | styleUrls: ['./welcome-component.component.css']
7 | })
8 | export class WelcomeComponentComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
--------------------------------------------------------------------------------
/src/app/shared/star/star.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, OnChanges, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-star',
5 | templateUrl: './star.component.html',
6 | styleUrls: ['./star.component.css']
7 | })
8 | export class StarComponent implements OnChanges {
9 | constructor() {}
10 |
11 | @Input() rating: number = 0;
12 | cropWidth: number = 75;
13 |
14 | ngOnChanges(): void {
15 | this.cropWidth = this.rating * (75 / 5);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import './polyfills';
2 |
3 | import { enableProdMode } from '@angular/core';
4 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
5 |
6 | import { AppModule } from './app/app.module';
7 |
8 | platformBrowserDynamic().bootstrapModule(AppModule).then(ref => {
9 | // Ensure Angular destroys itself on hot reloads.
10 | if (window['ngRef']) {
11 | window['ngRef'].destroy();
12 | }
13 | window['ngRef'] = ref;
14 |
15 | // Otherwise, log the boot error
16 | }).catch(err => console.error(err));
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "downlevelIteration": true,
9 | "experimentalDecorators": true,
10 | "module": "esnext",
11 | "moduleResolution": "node",
12 | "importHelpers": true,
13 | "target": "es2015",
14 | "typeRoots": [
15 | "node_modules/@types"
16 | ],
17 | "lib": [
18 | "es2018",
19 | "dom"
20 | ]
21 | },
22 | "angularCompilerOptions": {
23 | "enableIvy": true,
24 | "fullTemplateTypeCheck": true,
25 | "strictInjectionParameters": true
26 | }
27 | }
--------------------------------------------------------------------------------
/src/app/employee-component/employeedetail-component/employeedetail-component.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { ActivatedRoute, Router } from '@angular/router';
3 |
4 | @Component({
5 | templateUrl: './employeedetail-component.component.html',
6 | styleUrls: ['./employeedetail-component.component.css']
7 | })
8 | export class EmployeedetailComponentComponent implements OnInit {
9 | pageTitle: string = 'Employee Detail';
10 |
11 | constructor(private route: ActivatedRoute, private router: Router) {}
12 |
13 | ngOnInit() {
14 | const id = Number(this.route.snapshot.paramMap.get('id'));
15 | this.pageTitle += `: ${id}`;
16 | }
17 |
18 | onBack(): void {
19 | this.router.navigate(['/employees']);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/employee-component/employeedetail-component/employeedetail.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import {
3 | CanActivate,
4 | ActivatedRouteSnapshot,
5 | RouterStateSnapshot,
6 | Router
7 | } from '@angular/router';
8 | import { Observable } from 'rxjs';
9 |
10 | @Injectable({
11 | providedIn: 'root'
12 | })
13 | export class EmployeedetailGuard implements CanActivate {
14 | constructor(private router: Router) {}
15 |
16 | canActivate(
17 | next: ActivatedRouteSnapshot,
18 | state: RouterStateSnapshot
19 | ): Observable | Promise | boolean {
20 | const id = Number(next.paramMap.get('id'));
21 | if (isNaN(id) || id < 1) {
22 | alert('Invlaid Employee Id');
23 | this.router.navigate(['/employees']);
24 | return false;
25 | }
26 |
27 | return true;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/employee-component/employee-component.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Filter By: {{listFilter}}
8 |
9 |
10 |
11 |
12 | | Id |
13 | Code |
14 | Name |
15 | Salary |
16 | Rating |
17 |
18 |
19 | | {{employee.id}} |
20 | {{employee.code}} |
21 |
22 |
23 | {{employee.name}}
24 |
25 | |
26 | {{employee.salary}} |
27 |
28 |
29 | |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 | import { AppComponent } from './app.component';
4 | import { HttpClientModule } from '@angular/common/http';
5 | import { RouterModule } from '@angular/router';
6 | import { WelcomeComponentComponent } from './welcome-component/welcome-component.component';
7 | import { EmployeeModule } from './employee-component/employee.module';
8 |
9 | @NgModule({
10 | imports: [
11 | BrowserModule,
12 | HttpClientModule,
13 | RouterModule.forRoot([
14 | { path: 'welcome', component: WelcomeComponentComponent },
15 | { path: '', redirectTo: 'welcome', pathMatch: 'full' },
16 | { path: '**', redirectTo: 'welcome', pathMatch: 'full' }
17 | ]),
18 | EmployeeModule
19 | ],
20 | declarations: [AppComponent],
21 | bootstrap: [AppComponent]
22 | })
23 | export class AppModule {}
24 |
--------------------------------------------------------------------------------
/src/app/employee-component/employee.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { FormsModule } from '@angular/forms';
5 | import { RouterModule } from '@angular/router';
6 | import { EmployeeComponentComponent } from './employee-component.component';
7 | import { StarComponent } from '../shared/star/star.component';
8 | import { EmployeedetailComponentComponent } from './employeedetail-component/employeedetail-component.component';
9 | import { EmployeedetailGuard } from './employeedetail-component/employeedetail.guard';
10 |
11 | @NgModule({
12 | imports: [
13 | CommonModule,
14 | FormsModule,
15 | RouterModule.forChild([
16 | { path: 'employees', component: EmployeeComponentComponent },
17 | {
18 | path: 'employees/:id',
19 | component: EmployeedetailComponentComponent,
20 | canActivate: [EmployeedetailGuard]
21 | }
22 | ])
23 | ],
24 | declarations: [
25 | EmployeeComponentComponent,
26 | StarComponent,
27 | EmployeedetailComponentComponent
28 | ]
29 | })
30 | export class EmployeeModule {}
31 |
--------------------------------------------------------------------------------
/src/app/employee-component/employee.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpErrorResponse } from '@angular/common/http';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Injectable } from '@angular/core';
4 | import { Observable, throwError } from 'rxjs';
5 | import { catchError, tap } from 'rxjs/operators';
6 | import { IEmployee } from './employee';
7 |
8 | @Injectable({
9 | providedIn: 'root'
10 | })
11 | export class EmployeeService {
12 | constructor(private http: HttpClient) {}
13 |
14 | getEmployees(): Observable {
15 | return this.http
16 | .get('https://609e2e9f33eed80017957f8d.mockapi.io/employee')
17 | .pipe(
18 | tap(data => console.log('All', JSON.stringify(data))),
19 | catchError(this.handleError)
20 | );
21 | }
22 |
23 | private handleError(err: HttpErrorResponse) {
24 | let errorMessage = '';
25 | if (err.error instanceof ErrorEvent) {
26 | errorMessage = `An Error Occured:${err.error.message}`;
27 | } else {
28 | errorMessage = `Server returned code:${err.status}, error message is:${
29 | err.message
30 | }`;
31 | }
32 | console.log(errorMessage);
33 | return throwError(errorMessage);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular",
3 | "version": "0.0.0",
4 | "private": true,
5 | "dependencies": {
6 | "@angular/animations": "^12.1.0",
7 | "@angular/common": "^12.1.0",
8 | "@angular/compiler": "^12.1.0",
9 | "@angular/core": "^12.1.0",
10 | "@angular/forms": "^12.1.0",
11 | "@angular/platform-browser": "^12.1.0",
12 | "@angular/platform-browser-dynamic": "^12.1.0",
13 | "@angular/router": "^12.1.0",
14 | "@popperjs/core": "^2.9.3",
15 | "bootstrap": "^5.1.0",
16 | "font-awesome": "^4.7.0",
17 | "rxjs": "^7.1.0",
18 | "tslib": "^2.3.0",
19 | "zone.js": "^0.11.4"
20 | },
21 | "scripts": {
22 | "ng": "ng",
23 | "start": "ng serve",
24 | "build": "ng build",
25 | "test": "ng test",
26 | "lint": "ng lint",
27 | "e2e": "ng e2e"
28 | },
29 | "devDependencies": {
30 | "@angular-devkit/build-angular": "~0.1100.4",
31 | "@angular/cli": "~11.0.4",
32 | "@angular/compiler-cli": "~11.0.4",
33 | "@types/jasmine": "~3.6.0",
34 | "@types/node": "^12.11.1",
35 | "codelyzer": "^6.0.0",
36 | "jasmine-core": "~3.6.0",
37 | "jasmine-spec-reporter": "~5.0.0",
38 | "karma": "~5.1.0",
39 | "karma-chrome-launcher": "~3.1.0",
40 | "karma-coverage": "~2.0.3",
41 | "karma-jasmine": "~4.0.0",
42 | "karma-jasmine-html-reporter": "^1.5.0",
43 | "protractor": "~7.0.0",
44 | "ts-node": "~8.3.0",
45 | "tslint": "~6.1.0",
46 | "typescript": "~4.0.2"
47 | }
48 | }
--------------------------------------------------------------------------------
/src/app/employee-component/employee-component.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnDestroy, OnInit } from '@angular/core';
2 | import { Subscription } from 'rxjs';
3 | import { IEmployee } from './employee';
4 | import { EmployeeService } from './employee.service';
5 |
6 | @Component({
7 | selector: 'app-employee-component',
8 | templateUrl: './employee-component.component.html',
9 | styleUrls: ['./employee-component.component.css']
10 | })
11 | export class EmployeeComponentComponent implements OnInit, OnDestroy {
12 | sub!: Subscription;
13 | private _listFilter: string = '';
14 | private errorMessage: string = '';
15 | filteredEmployees: IEmployee[] = [];
16 | employees: IEmployee[] = [];
17 |
18 | constructor(private employeeService: EmployeeService) {}
19 |
20 | //ALTERNATIVE CODE OF CONSTRUCTOR
21 | // private employeeService;
22 | // constructor(employeeService: EmployeeService) {
23 | // this.employeeService = employeeService;
24 | // }
25 |
26 | ngOnInit() {
27 | this.sub = this.employeeService.getEmployees().subscribe({
28 | next: employees => {
29 | this.employees = employees;
30 | this.filteredEmployees = this.employees;
31 | },
32 | error: err => (this.errorMessage = err)
33 | });
34 | }
35 |
36 | get listFilter(): string {
37 | return this._listFilter;
38 | }
39 |
40 | set listFilter(value: string) {
41 | this._listFilter = value;
42 | console.log('In Setter:', value);
43 | this.filteredEmployees = this.performFilter(value);
44 | }
45 |
46 | performFilter(filterBy: string): IEmployee[] {
47 | filterBy = filterBy.toLocaleLowerCase();
48 | return this.employees.filter((employee: IEmployee) =>
49 | employee.name.toLocaleLowerCase().includes(filterBy)
50 | );
51 | }
52 |
53 | ngOnDestroy() {
54 | this.sub.unsubscribe();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/
22 | // import 'core-js/es6/symbol';
23 | // import 'core-js/es6/object';
24 | // import 'core-js/es6/function';
25 | // import 'core-js/es6/parse-int';
26 | // import 'core-js/es6/parse-float';
27 | // import 'core-js/es6/number';
28 | // import 'core-js/es6/math';
29 | // import 'core-js/es6/string';
30 | // import 'core-js/es6/date';
31 | // import 'core-js/es6/array';
32 | // import 'core-js/es6/regexp';
33 | // import 'core-js/es6/map';
34 | // import 'core-js/es6/set';
35 |
36 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
37 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
38 |
39 | /** IE10 and IE11 requires the following to support `@angular/animation`. */
40 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
41 |
42 |
43 | /** Evergreen browsers require these. **/
44 | // import 'core-js/es6/reflect';
45 | // import 'core-js/es7/reflect';
46 |
47 |
48 | /**
49 | * Web Animations `@angular/platform-browser/animations`
50 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
51 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
52 | */
53 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
54 |
55 |
56 |
57 | /***************************************************************************************************
58 | * Zone JS is required by Angular itself.
59 | */
60 | import 'zone.js/dist/zone'; // Included with Angular CLI.
61 |
62 |
63 | /***************************************************************************************************
64 | * APPLICATION IMPORTS
65 | */
66 |
67 | /**
68 | * Date, currency, decimal and percent pipes.
69 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
70 | */
71 | // import 'intl'; // Run `npm install --save intl`.
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "demo": {
7 | "root": "",
8 | "sourceRoot": "src",
9 | "projectType": "application",
10 | "prefix": "app",
11 | "schematics": {},
12 | "architect": {
13 | "build": {
14 | "builder": "@angular-devkit/build-angular:browser",
15 | "options": {
16 | "outputPath": "dist/demo",
17 | "index": "src/index.html",
18 | "main": "src/main.ts",
19 | "polyfills": "src/polyfills.ts",
20 | "tsConfig": "src/tsconfig.app.json",
21 | "assets": [
22 | "src/favicon.ico",
23 | "src/assets"
24 | ],
25 | "styles": [
26 | "src/styles.css"
27 | ],
28 | "scripts": []
29 | },
30 | "configurations": {
31 | "production": {
32 | "fileReplacements": [
33 | {
34 | "replace": "src/environments/environment.ts",
35 | "with": "src/environments/environment.prod.ts"
36 | }
37 | ],
38 | "optimization": true,
39 | "outputHashing": "all",
40 | "sourceMap": false,
41 | "extractCss": true,
42 | "namedChunks": false,
43 | "aot": true,
44 | "extractLicenses": true,
45 | "vendorChunk": false,
46 | "buildOptimizer": true
47 | }
48 | }
49 | },
50 | "serve": {
51 | "builder": "@angular-devkit/build-angular:dev-server",
52 | "options": {
53 | "browserTarget": "demo:build"
54 | },
55 | "configurations": {
56 | "production": {
57 | "browserTarget": "demo:build:production"
58 | }
59 | }
60 | },
61 | "extract-i18n": {
62 | "builder": "@angular-devkit/build-angular:extract-i18n",
63 | "options": {
64 | "browserTarget": "demo:build"
65 | }
66 | },
67 | "test": {
68 | "builder": "@angular-devkit/build-angular:karma",
69 | "options": {
70 | "main": "src/test.ts",
71 | "polyfills": "src/polyfills.ts",
72 | "tsConfig": "src/tsconfig.spec.json",
73 | "karmaConfig": "src/karma.conf.js",
74 | "styles": [
75 | "styles.css"
76 | ],
77 | "scripts": [],
78 | "assets": [
79 | "src/favicon.ico",
80 | "src/assets"
81 | ]
82 | }
83 | },
84 | "lint": {
85 | "builder": "@angular-devkit/build-angular:tslint",
86 | "options": {
87 | "tsConfig": [
88 | "src/tsconfig.app.json",
89 | "src/tsconfig.spec.json"
90 | ],
91 | "exclude": [
92 | "**/node_modules/**"
93 | ]
94 | }
95 | }
96 | }
97 | }
98 | },
99 | "defaultProject": "demo"
100 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular-featuremodule
2 |
3 | employee.ts (parent)
4 |
5 | ```js
6 | export interface IEmployee {
7 | id: number;
8 | code: string;
9 | name: string;
10 | salary: number;
11 | starRating: number;
12 | }
13 | ```
14 |
15 | employee.service.ts
16 |
17 | ```js
18 | import { HttpErrorResponse } from '@angular/common/http';
19 | import { HttpClient } from '@angular/common/http';
20 | import { Injectable } from '@angular/core';
21 | import { Observable, throwError } from 'rxjs';
22 | import { catchError, tap } from 'rxjs/operators';
23 | import { IEmployee } from './employee';
24 |
25 | @Injectable({
26 | providedIn: 'root'
27 | })
28 | export class EmployeeService {
29 | constructor(private http: HttpClient) {}
30 |
31 | getEmployees(): Observable {
32 | return this.http
33 | .get('https://609e2e9f33eed80017957f8d.mockapi.io/employee')
34 | .pipe(
35 | tap(data => console.log('All', JSON.stringify(data))),
36 | catchError(this.handleError)
37 | );
38 | }
39 |
40 | private handleError(err: HttpErrorResponse) {
41 | let errorMessage = '';
42 | if (err.error instanceof ErrorEvent) {
43 | errorMessage = `An Error Occured:${err.error.message}`;
44 | } else {
45 | errorMessage = `Server returned code:${err.status}, error message is:${
46 | err.message
47 | }`;
48 | }
49 | console.log(errorMessage);
50 | return throwError(errorMessage);
51 | }
52 | }
53 | ```
54 |
55 | employee-component.component.ts (parent)
56 |
57 | ```js
58 | import { Component, OnDestroy, OnInit } from '@angular/core';
59 | import { Subscription } from 'rxjs';
60 | import { IEmployee } from './employee';
61 | import { EmployeeService } from './employee.service';
62 |
63 | @Component({
64 | selector: 'app-employee-component',
65 | templateUrl: './employee-component.component.html',
66 | styleUrls: ['./employee-component.component.css']
67 | })
68 | export class EmployeeComponentComponent implements OnInit, OnDestroy {
69 | sub!: Subscription;
70 | private _listFilter: string = '';
71 | private errorMessage: string = '';
72 | filteredEmployees: IEmployee[] = [];
73 | employees: IEmployee[] = [];
74 |
75 | constructor(private employeeService: EmployeeService) {}
76 |
77 | //ALTERNATIVE CODE OF CONSTRUCTOR
78 | // private employeeService;
79 | // constructor(employeeService: EmployeeService) {
80 | // this.employeeService = employeeService;
81 | // }
82 |
83 | ngOnInit() {
84 | this.sub = this.employeeService.getEmployees().subscribe({
85 | next: employees => {
86 | this.employees = employees;
87 | this.filteredEmployees = this.employees;
88 | },
89 | error: err => (this.errorMessage = err)
90 | });
91 | }
92 |
93 | get listFilter(): string {
94 | return this._listFilter;
95 | }
96 |
97 | set listFilter(value: string) {
98 | this._listFilter = value;
99 | console.log('In Setter:', value);
100 | this.filteredEmployees = this.performFilter(value);
101 | }
102 |
103 | performFilter(filterBy: string): IEmployee[] {
104 | filterBy = filterBy.toLocaleLowerCase();
105 | return this.employees.filter((employee: IEmployee) =>
106 | employee.name.toLocaleLowerCase().includes(filterBy)
107 | );
108 | }
109 |
110 | ngOnDestroy() {
111 | this.sub.unsubscribe();
112 | }
113 | }
114 | ```
115 | employee-component.component.html (parent)
116 |
117 | ```html
118 |
119 |
120 |
121 |
122 |
123 |
124 | Filter By: {{listFilter}}
125 |
126 |
127 |
128 |
129 | | Id |
130 | Code |
131 | Name |
132 | Salary |
133 | Rating |
134 |
135 |
136 | | {{employee.id}} |
137 | {{employee.code}} |
138 |
139 |
140 | {{employee.name}}
141 |
142 | |
143 | {{employee.salary}} |
144 |
145 |
146 | |
147 |
148 |
149 |
150 |
151 | ```
152 | star.component.ts (child)
153 |
154 | ```js
155 | import { Component, Input, OnChanges, OnInit } from '@angular/core';
156 |
157 | @Component({
158 | selector: 'app-star',
159 | templateUrl: './star.component.html',
160 | styleUrls: ['./star.component.css']
161 | })
162 | export class StarComponent implements OnChanges {
163 | constructor() {}
164 |
165 | @Input() rating: number = 0;
166 | cropWidth: number = 75;
167 |
168 | ngOnChanges(): void {
169 | this.cropWidth = this.rating * (75 / 5);
170 | }
171 | }
172 | ```
173 |
174 | star.component.html (child)
175 |
176 | ```html
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 | ```
187 |
188 | star.component.css (child)
189 |
190 | ```css
191 | .crop {
192 | overflow: hidden;
193 | }
194 | div {
195 | cursor: pointer;
196 | }
197 | ```
198 |
199 | employeedetail-component.component.ts
200 |
201 | ```js
202 | import { Component, OnInit } from '@angular/core';
203 | import { ActivatedRoute, Router } from '@angular/router';
204 |
205 | @Component({
206 | templateUrl: './employeedetail-component.component.html',
207 | styleUrls: ['./employeedetail-component.component.css']
208 | })
209 | export class EmployeedetailComponentComponent implements OnInit {
210 | pageTitle: string = 'Employee Detail';
211 |
212 | constructor(private route: ActivatedRoute, private router: Router) {}
213 |
214 | ngOnInit() {
215 | const id = Number(this.route.snapshot.paramMap.get('id'));
216 | this.pageTitle += `: ${id}`;
217 | }
218 |
219 | onBack(): void {
220 | this.router.navigate(['/employees']);
221 | }
222 | }
223 | ```
224 |
225 | employeedetail-component.component.html
226 |
227 | ```html
228 |
229 |
232 |
237 |
238 | ```
239 |
240 | employeedetails.guard.ts
241 |
242 | ```js
243 | import { Injectable } from '@angular/core';
244 | import {
245 | CanActivate,
246 | ActivatedRouteSnapshot,
247 | RouterStateSnapshot,
248 | Router
249 | } from '@angular/router';
250 | import { Observable } from 'rxjs';
251 |
252 | @Injectable({
253 | providedIn: 'root'
254 | })
255 | export class EmployeedetailGuard implements CanActivate {
256 | constructor(private router: Router) {}
257 |
258 | canActivate(
259 | next: ActivatedRouteSnapshot,
260 | state: RouterStateSnapshot
261 | ): Observable | Promise | boolean {
262 | const id = Number(next.paramMap.get('id'));
263 | if (isNaN(id) || id < 1) {
264 | alert('Invlaid Employee Id');
265 | this.router.navigate(['/employees']);
266 | return false;
267 | }
268 |
269 | return true;
270 | }
271 | }
272 | ```
273 |
274 | welcome-component.component.ts
275 |
276 | ```js
277 | import { Component, OnInit } from '@angular/core';
278 |
279 | @Component({
280 | selector: 'app-welcome-component',
281 | templateUrl: './welcome-component.component.html',
282 | styleUrls: ['./welcome-component.component.css']
283 | })
284 | export class WelcomeComponentComponent implements OnInit {
285 |
286 | constructor() { }
287 |
288 | ngOnInit() {
289 | }
290 |
291 | }
292 | ```
293 |
294 | welcome-component.component.html
295 |
296 | ```html
297 |
298 | Welcome Works!
299 |
300 | ```
301 |
302 | employee.module.ts
303 |
304 | ```js
305 | import { NgModule } from '@angular/core';
306 | import { CommonModule } from '@angular/common';
307 |
308 | import { FormsModule } from '@angular/forms';
309 | import { RouterModule } from '@angular/router';
310 | import { EmployeeComponentComponent } from './employee-component.component';
311 | import { StarComponent } from '../shared/star/star.component';
312 | import { EmployeedetailComponentComponent } from './employeedetail-component/employeedetail-component.component';
313 | import { EmployeedetailGuard } from './employeedetail-component/employeedetail.guard';
314 |
315 | @NgModule({
316 | imports: [
317 | CommonModule,
318 | FormsModule,
319 | RouterModule.forChild([
320 | { path: 'employees', component: EmployeeComponentComponent },
321 | {
322 | path: 'employees/:id',
323 | component: EmployeedetailComponentComponent,
324 | canActivate: [EmployeedetailGuard]
325 | }
326 | ])
327 | ],
328 | declarations: [
329 | EmployeeComponentComponent,
330 | StarComponent,
331 | EmployeedetailComponentComponent
332 | ]
333 | })
334 | export class EmployeeModule {}
335 |
336 | ```
337 |
338 |
339 | style.css
340 |
341 | Install bootstrap font-awesome and import in style.css
342 |
343 | ```css
344 | @import '~bootstrap/dist/css/bootstrap.min.css';
345 | @import 'font-awesome/css/font-awesome.min.css';
346 | ```
347 |
348 | app.module.ts
349 |
350 | ```js
351 | import { NgModule } from '@angular/core';
352 | import { BrowserModule } from '@angular/platform-browser';
353 | import { AppComponent } from './app.component';
354 | import { HttpClientModule } from '@angular/common/http';
355 | import { RouterModule } from '@angular/router';
356 | import { WelcomeComponentComponent } from './welcome-component/welcome-component.component';
357 | import { EmployeeModule } from './employee-component/employee.module';
358 |
359 | @NgModule({
360 | imports: [
361 | BrowserModule,
362 | HttpClientModule,
363 | RouterModule.forRoot([
364 | { path: 'welcome', component: WelcomeComponentComponent },
365 | { path: '', redirectTo: 'welcome', pathMatch: 'full' },
366 | { path: '**', redirectTo: 'welcome', pathMatch: 'full' }
367 | ]),
368 | EmployeeModule
369 | ],
370 | declarations: [AppComponent],
371 | bootstrap: [AppComponent]
372 | })
373 | export class AppModule {}
374 |
375 | ```
376 |
377 | app.component.html
378 |
379 | ```html
380 |
398 |
399 |
400 |
401 | ```
402 | 
403 |
404 | 
405 |
406 |
407 |
408 |
409 |
410 |
411 |
--------------------------------------------------------------------------------