Angular Essentials
Angular Introduction:
Angular is a popular open-source web application framework maintained by Google and a community of developers. It's used for building single-page client applications in HTML and TypeScript. Here's a breakdown of some key concepts and features to give you an introduction:
Architecture: Angular follows the MVC (Model-View-Controller) architecture pattern, but it's often described in terms of components. Components are the basic building blocks of an Angular application. Each component consists of three parts:
Interpolation: Allows you to embed expressions in HTML templates.
Dependency Injection: Angular has a built-in dependency injection system that helps manage the dependencies of components and services. This promotes modularity, reusability, and testability of code.
Routing: Angular provides a powerful router module that allows you to build single-page applications with multiple views. You can define routes for different URLs and load the appropriate components when those URLs are navigated to.
Directives: Directives are markers on a DOM element that tell Angular to do something with that element, such as modify its behavior or appearance. Angular comes with built-in directives like ngFor and ngIf, and you can also create custom directives to extend the framework's functionality.
Services: Services are singleton objects that are instantiated only once during the lifetime of an application. They are used to encapsulate logic that is not specific to any component, such as data access, logging, or communication with a backend server.
Modules: Angular applications are modular and organized into NgModules. Each NgModule declares a set of components, directives, pipes, and services that are related to each other. This helps in organizing the application into cohesive blocks of functionality.
History of Angular:
AngularJS (2009-2016):
Angular 2+ (2016-present):
Angular Ivy (2019-present):
1. Download Nodejs in chrome.
----------------------------------------------------------------------------------------------------
2. node --version --> To check the nodejs version
3. npm --version --> To check the npm version
----------------------------------------------------------------------------------------------------
4. To Install the Angular Software:
npm install -g @angular/cli
----------------------------------------------------------------------------------------------------
5. To Create a new Project
ng new ProjectName
If the Project does not contains Module File --> ng new ProjectName --no-standalone
----------------------------------------------------------------------------------------------------
6. To open a Project in the VS code
code ProjectName
----------------------------------------------------------------------------------------------------
7. To Create a Component
ng g c ComponentName
g --> generate
c --> Component
----------------------------------------------------------------------------------------------------
8. To install a Bootstrap in Angular
ng install bootstrap --save
----------------------------------------------------------------------------------------------------
9. To install jquery in Angular
ng install jquery --save
----------------------------------------------------------------------------------------------------
10. To Run a Project
ng serve
----------------------------------------------------------------------------------------------------
Data Binding:
In Angular, data binding is a powerful feature that allows you to define communication between a component and its template. It synchronizes the data between the component and the view, making it easy to build dynamic and interactive web applications.
Interpolation{{}}:
interpolation is a form of one-way data binding where you bind data from the component class to the template. You enclose the expression within double curly braces ({{...}}) in the template, and Angular replaces it with the evaluated value.
Example:
Property Binding:
Property binding allows you to set an element's property to the value of a template expression. You use square brackets ([]) to bind the property to the component's property.
Event Binding:
Two way Binding:
Two-way data binding in Angular allows you to establish a bidirectional data flow between a property of a component and an input field in the template. This means changes to the property in the component class are reflected in the template, and changes made in the template are propagated back to the component class.
In Angular, two-way data binding is typically achieved using the ngModel directive along with banana-in-a-box syntax [(ngModel)]. To use two-way data binding, you need to import the FormsModule or ReactiveFormsModule in your Angular module.
Directives:
In Angular, directives play a crucial role in enhancing the behavior and appearance of elements within your application. Let’s delve into the different types of directives:
Component Directive:
Components are the most common type of directive in Angular. They are used to create reusable UI components with their own templates, styles, and behavior. Components are essentially directives with a template.
Structural Directive:
Structural directives change the structure of the DOM by adding, removing, or manipulating elements based on conditions. They are preceded by an asterisk (*) in the template syntax.
Example:
*ngFor:
*ngFor is a structural directive in Angular used for rendering lists of items. It allows you to iterate over a collection of data and generate HTML elements for each item in the collection. The *ngFor directive is often used in conjunction with an array or an iterable object to dynamically create a set of elements based on the data.
Output:
*ngFor with an array of Object:
Output:
*ngIf:
In Angular, the ngIf directive serves to dynamically remove or recreate sections of HTML elements based on an expression. When the expression evaluates to false, the corresponding element is removed from the DOM. Conversely, if the expression is true, the element is added to the DOM.
In Angular, ngIf can be paired with ngElse to define an alternative content when the condition is false, and ngIf can also be combined with ngThen and ngIfElse for asynchronous operations to show loading states.
Output:
ng-else:
ng-then:
Attribute Directive:
Attribute directives are a type of directive in Angular that allow you to change the behavior or appearance of an element, component, or another directive.
ngClass:
Pipes:
Pipes |
Definition |
Date Pipe |
Formats a date value according to locale rules. |
UpperCase Pipe |
Transforms text to all upper case. |
LowerCase Pipe |
Transforms text to all lower case. |
Currency Pipe |
Transforms a number to a currenct string, formatted according to local rules. |
Decimal Pipe |
Transforms a number into a string with a decimal point, formatted according to locale rules. |
Percent Pipe |
Transforms a number to a percentage string, formatted according to locale rules. |
Async Pipe |
Subscribe and unsubscribe to an asynchronous source such as an observable.
|
Json Pipe |
Display a component object property to the screen as JSON for debugging.
|
Slice Pipe |
Creates a new Array or String containing a subset (slice) of the elements. |
DatePipe:
Formats |
Equivalent to |
Examples |
'short' |
'M/d/yy, h:mm a' |
6/15/24, 9:03 AM |
'medium' |
'MMM d, y, h:mm:ss a' |
April 15, 2024, 9:03:01 AM |
'long' |
'MMMM d, y, h:mm:ss a z' |
April 15, 2024 at 9:03:01 AM GMT+1 |
'full' |
'EEEE, MMMM d, y, h:mm:ss a zzzz' |
Monday, April 15, 2024 at 9:03:01 AM GMT+01:00 |
'shortDate' |
'M/d/yy' |
6/15/24 |
'mediumDate' |
'MMM d, y' |
April 15, 2024 |
'longDate' |
'MMMM d, y' |
April 15, 2024 |
'fullDate' |
'EEEE, MMMM d, y' |
Monday, April 15, 2024 |
'shortTime' |
'h:mm a' |
9:03 AM |
'mediumTime' |
'h:mm:ss a' |
9:03:01 AM |
'longTime' |
'h:mm:ss a z' |
9:03:01 AM GMT+1 |
'fullTime' |
'h:mm:ss a zzzz' |
9:03:01 AM GMT+01:00 |
UpperCase and LowerCase:
The uppercase and lowercase pipes in Angular are used to transform text to either all uppercase or all lowercase, respectively.
For example:
{{ text | uppercase }} will transform the text variable to all uppercase letters.
{{ text | lowercase }} will transform the text variable to all lowercase letters.
SlicePipe:
The slice pipe in Angular is used to create a new array or string containing a subset of the elements or characters from the original array or string.
It takes two arguments: the starting index and the optional ending index.
For arrays:
If only one argument is provided, it returns elements starting from the specified index to the end of the array.
If both arguments are provided, it returns elements from the starting index up to (but not including) the ending index.
For strings:
If only one argument is provided, it returns characters starting from the specified index to the end of the string.
If both arguments are provided, it returns characters from the starting index up to (but not including) the ending index.
Currency Pipe:
The currency pipe in Angular is used to format numbers as currency values. It takes an optional currency code as an argument, which specifies the currency symbol to use in the formatted output.
The pipe also accepts additional parameters for specifying the display of currency symbols, decimal separators, and digit grouping.
Dependency Injection:
Dependency Injection (DI) is a core concept in Angular, a popular JavaScript framework for building web applications. In Angular, DI is used to manage the dependencies between different parts of an application.
Dependency Injection Container: Angular maintains a hierarchical tree of dependency injection containers. Each Angular application has a single root container, and each component has its own injector. When Angular creates a component, it creates an injector for that component and its children.
Providers: Providers are the way to register dependencies in Angular. You can register providers at various levels: at the module level, component level, or even at the application level. Providers tell Angular how to create instances of the dependencies when they are needed.
Injectors: Injectors are responsible for resolving dependencies. When a component requests a dependency, Angular's injector looks up the provider for that dependency and creates an instance if it hasn't already been created. Angular resolves dependencies based on the hierarchical structure of the application.
Dependency Injection in Components: You can inject dependencies into Angular components by specifying them as parameters in the component's constructor. Angular's DI system automatically resolves these dependencies and provides them when the component is instantiated.
In this example, MyComponent depends on MyService. By specifying private myService: MyService in the constructor, Angular knows that MyComponent requires an instance of MyService. Angular's DI system takes care of providing an instance of MyService when MyComponent is created.
Service:
In Angular, a service is a class that provides reusable functionality across the application. Services are typically used for encapsulating logic that can be shared across multiple components, such as data fetching, business logic, state management, or interacting with APIs.
Creating and Using a Service in Angular:
1. Creating a Service
You can create a service using Angular CLI:
This command generates a service file (my-service.service.ts) and a corresponding spec file for testing.
2. Defining a Service
In the generated service file, you define your service class and its methods. Here's an example of a basic data service:
import { Component, OnInit } from '@angular/core'; import { MyService } from '../my-service.service';
@Component({ selector: 'app-my-component', templateUrl: './my-component.component.html', styleUrls: ['./my-component.component.css'] }) export class MyComponent implements OnInit {
data: any[];
constructor(private myService: MyService) { }
ngOnInit(): void { this.fetchData(); }
fetchData(): void { this.myService.getData().subscribe( (response) => { this.data = response; }, (error) => { console.error('Error fetching data', error); } ); }
addData(newData: any): void { this.myService.addData(newData).subscribe( (response) => { this.data.push(response); }, (error) => { console.error('Error adding data', error); } ); }
updateData(id: number, updatedData: any): void { this.myService.updateData(id, updatedData).subscribe( (response) => { const index = this.data.findIndex(item => item.id === id); if (index !== -1) { this.data[index] = response; } }, (error) => { console.error('Error updating data', error); } ); }
deleteData(id: number): void { this.myService.deleteData(id).subscribe( () => { this.data = this.data.filter(item => item.id !== id); }, (error) => { console.error('Error deleting data', error); } ); } } |
3. Injecting a Service into a Component
To use the service in a component, inject it via the component's constructor:
import { Component, OnInit } from '@angular/core'; import { MyService } from '../my-service.service';
@Component({ selector: 'app-my-component', templateUrl: './my-component.component.html', styleUrls: ['./my-component.component.css'] }) export class MyComponent implements OnInit {
data: any[];
constructor(private myService: MyService) { }
ngOnInit(): void { this.fetchData(); }
fetchData(): void { this.myService.getData().subscribe( (response) => { this.data = response; }, (error) => { console.error('Error fetching data', error); } ); }
addData(newData: any): void { this.myService.addData(newData).subscribe( (response) => { this.data.push(response); }, (error) => { console.error('Error adding data', error); } ); }
updateData(id: number, updatedData: any): void { this.myService.updateData(id, updatedData).subscribe( (response) => { const index = this.data.findIndex(item => item.id === id); if (index !== -1) { this.data[index] = response; } }, (error) => { console.error('Error updating data', error); } ); }
deleteData(id: number): void { this.myService.deleteData(id).subscribe( () => { this.data = this.data.filter(item => item.id !== id); }, (error) => { console.error('Error deleting data', error); } ); } } |
4. Service Providers
Services can be provided at different levels in an Angular application:
Root Level: By specifying { providedIn: 'root' } in the @Injectable decorator, the service is provided at the root level, making it a singleton instance available throughout the application.
Module Level: You can provide services in specific Angular modules by adding them to the providers array in the module's @NgModule decorator.
Component Level: Although less common, services can also be provided at the component level by adding them to the providers array in the component's @Component decorator. This creates a new instance of the service for that component and its children.
Example of providing a service at the module level:
Benefits of Using Services
Encapsulation: Services encapsulate related logic, making it easier to manage and test.
Reusability: Services can be reused across different components and modules, reducing code duplication.
Testability: Services are easy to unit test because they are independent of the components that use them.
Maintainability: By separating business logic from UI logic, services help keep the codebase organized and easier to maintain.
Routing:
Routing in the context of web development and Angular refers to the mechanism of navigating between different views or pages in a single-page application (SPA). In an SPA, instead of loading entire new pages from the server, different views are dynamically loaded and displayed based on the URL, while the application remains on the same page. This leads to a smoother and faster user experience.
Key Concepts of Routing
Routes:
Routes define the mapping between URL paths and the components that should be displayed when those paths are accessed. Each route typically specifies a path and the component to load.
Router:
The router is the core service responsible for interpreting the browser's URL and managing the application's view state accordingly. It handles navigation, updates the browser's history, and can manage complex routing configurations.
Route Configuration:
Route configuration is the process of defining routes in an application. This is usually done in a routing module where routes are declared as an array of route objects.
Router Outlet:
The <router-outlet> directive is a placeholder in the template where the matched component's view will be inserted.
Navigation:
Navigation refers to moving between different views. This can be done using router links in templates or programmatically using the router service.
Lazy Loading:
Lazy loading is the practice of loading modules only when they are needed, which can improve the initial load time of the application. Routes can be configured to lazy load specific modules.
Route Guards:
Route guards are services that decide whether a route can be activated or deactivated. They are used for implementing authentication, authorization, and other conditional navigation logic.
Example of Routing in Angular
Setting Up Routes
In Angular, routes are typically defined in a separate module, such as app-routing.module.ts. Here’s an example configuration:
Importing the Router Module
Ensure the AppRoutingModule is imported into the main application module (app.module.ts):
Adding Navigation Links
Add navigation links in your main component's template (app.component.html):
Forms and Validation:
In Angular, forms and validation are crucial for capturing and validating user input. Angular provides two types of forms: template-driven forms and reactive forms.
Template Driven Forms:
Template-driven forms are simpler to set up and manage, leveraging Angular's two-way data binding and directives.
Validation:
Angular provides validation directives such as required, minlength, maxlength, pattern, etc.
Error handling can be managed using template references (e.g., #username="ngModel").
Common Validation:
Authentication:
Authentication is the process of verifying the identity of a user. In Angular, this typically involves:
Login Form: A user provides credentials (usually a username/email and password) via a login form.
Service for Authentication: An Angular service sends these credentials to a backend server.
Backend Verification: The backend server verifies the credentials and, if valid, returns a token (e.g., JWT - JSON Web Token) or session information.
Storing the Token: The Angular application stores this token, typically in localStorage or sessionStorage, to keep the user authenticated.
Example:
Login Component
Auth Service:
Auth Guard:
Authorization:
Authorization is the process of determining whether a user has permission to perform a certain action or access a certain resource. This is typically done after the user has been authenticated.
In Angular, authorization is often implemented using roles and guards:
Role-Based Access Control: Define roles for users and restrict access to certain parts of the application based on these roles.
Guards: Angular's route guards (CanActivate, CanActivateChild, etc.) are used to control access to different routes.
Example
Auth Service with Roles:
Guard for Role based Access:
Defining Routes With Guards:
Angular Modules:
Angular modules are a core concept in Angular, an application design framework and development platform for building efficient and sophisticated single-page apps. Angular modules, often referred to as NgModules, are used to group related code into functional sets, making the code more organized, maintainable, and scalable.
Key Concepts of Angular Modules
NgModule Definition:
An Angular module is defined using the @NgModule decorator, which is a class decorator that takes a metadata object describing how to compile a component's template and how to create an injector at runtime.
Metadata Properties:
The @NgModule decorator has several properties that configure the module:
declarations: This property lists the components, directives, and pipes that belong to this module.
imports: This property lists other modules whose exported classes are needed by component templates declared in this module.
exports: This property lists the components, directives, and pipes that can be used in the templates of components in other modules.
providers: This property lists the services and other providers that the module contributes to the global collection of services; these services become available in any part of the application.
bootstrap: This property lists the component(s) that should be bootstrapped when this module is bootstrapped. Typically, this list contains a single component, the root component of the application.
Root Module:
Every Angular application has at least one module, the root module, which is typically named AppModule. The root module is the entry point for the application and bootstraps the root component.
Feature Modules:
To better organize an application, you can create feature modules. These are additional modules that encapsulate a particular feature, allowing you to separate different parts of the application logically and physically. Feature modules can be imported into the root module or other feature modules.
Shared Modules:
Shared modules are used to organize and re-use common components, directives, and pipes. They can be imported into feature modules to avoid redundancy.
Lazy Loading:
Modules can be loaded on demand, rather than at application startup. This technique, called lazy loading, can significantly improve the performance of large applications by dividing them into smaller, more manageable parts.
Angular CLI Commands and Tools:
Angular CLI (Command Line Interface) is a powerful tool for Angular development that simplifies the process of creating, managing, and deploying Angular applications. It provides a suite of commands and tooling that help developers streamline their workflow, enforce best practices, and automate repetitive tasks.
Installation
To use Angular CLI, you need to install it globally using npm:
Common Commands
Creating a New Angular Project
ng new project-name
This command creates a new Angular project with the specified name, setting up the initial file structure and configuration
Serving an Application
This command compiles the application and serves it using a local development server. The default address is http://localhost:4200.
Generating Components, Services, and Other Elements
The ng generate command (or the shorthand ng g) helps scaffold various elements of an Angular application, reducing the boilerplate code.
Building the Application:
This command compiles the application into an output directory (dist/ by default). It can also accept flags for production builds, such as --prod for optimizations.
Running Unit Tests
This command runs the unit tests for the application using the configured test runner (e.g., Karma).
Running End-to-End Tests
This command runs end-to-end tests using Protractor.
Linting the Code
This command analyzes the project's code for linting errors using TSLint.
Updating Angular CLI and Core
This command updates Angular CLI and the Angular core framework to the latest versions, applying necessary migrations.
Adding Features to Your Project
The ng add command installs and configures libraries and tools in your project. For example, adding Angular Material or PWA support.
Configuring the Project
This command reads and modifies Angular configuration settings in the angular.json file.
Tooling
Angular Schematics
Angular CLI uses schematics to apply transformations to the project. Schematics can be used to generate files, update dependencies, or apply code modifications. Custom schematics can also be created for specific project needs.
Builder API
Builders in Angular CLI are used for running tasks like build, serve, test, and lint. They are customizable and can be extended for specific workflows or integrated with other tools.
Configuration Files
Optimizing Angular Application:
Optimizing Angular applications involves a range of techniques and best practices aimed at improving the performance, speed, and efficiency of Angular apps. Here are some key strategies and methods for optimizing Angular applications:
1. AOT (Ahead-of-Time) Compilation
Description: AOT compiles your Angular components and templates during the build process. This results in faster rendering in the browser because the code is already compiled.
Implementation: Enable AOT by default in your build configurations. In Angular CLI, this can be done by using the --aot flag during build commands:
2. Lazy Loading
Description: Lazy loading loads modules only when they are needed, reducing the initial load time of the application.
Implementation: Configure your Angular routes to load modules lazily. For example:
3. Code Splitting
Description: Code splitting breaks your application into smaller bundles, which are loaded on demand.
Implementation: Angular CLI handles this automatically when using lazy loading, but you can also use Webpack configuration for more advanced scenarios.
4. Tree Shaking
Description: Tree shaking removes unused code from your final bundle.
Implementation: Ensure your build process uses tools like UglifyJS or Terser, which are integrated into Angular CLI, to perform tree shaking.