0% found this document useful (0 votes)
21 views36 pages

WE Notes Unit - III, IV Complete (R-18)

Notes

Uploaded by

babjichintu123
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views36 pages

WE Notes Unit - III, IV Complete (R-18)

Notes

Uploaded by

babjichintu123
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

WE Notes Unit - III,IV Complete (R-18)

Unit - III (Node, Express & Type Script)

Q1. Build a REST API using Node.js and Consume it in react with CRUD
Operations
A.) A REST (Representational State Transfer) API is an architectural style for designing networked applications. It relies on
a stateless, client-server, cacheable communications protocol, typically HTTP. REST APIs allow different systems to
communicate with each other over the internet in a standardized way. Here’s an overview of what a REST API is and how it
works:

Key Characteristics of REST APIs


1. Stateless:
Each request from a client to a server must contain all the information the server needs to understand and process the
request. The server does not store any state about the client session on its side.

2. Client-Server Architecture:
The client and server are separate entities, allowing them to evolve independently. The client is responsible for the user
interface and user state, while the server manages application state and resources.

3. Cacheable:
Responses from the server must define themselves as cacheable or non-cacheable, allowing clients to cache responses to
improve performance.

4. Uniform Interface:
REST APIs use standard methods and conventions for interacting with resources, which simplifies and decouples the
architecture. The uniform interface typically involves the use of standard HTTP methods.

HTTP Methods in REST APIs


1. GET:
Retrieve a resource or a list of resources from the server. It should not alter the state of the resource.

2. POST:
Create a new resource on the server.

3. PUT:
Update an existing resource on the server. If the resource does not exist, it can create a new one (though this is less
common).

4. PATCH:
Partially update an existing resource on the server.

5. DELETE:
Remove a resource from the server.

Resource Identification
Resources in a REST API are identified by URLs (Uniform Resource Locators). Each URL represents a specific resource or
collection of resources. For example:

WE Notes Unit - III,IV Complete (R-18) 1


/users might represent a collection of users.

/users/123 might represent a specific user with the ID 123 .

Example of a REST API


Let’s consider a simple REST API for managing users.

GET /users:
Retrieves a list of users.

[
{ "id": 1, "name": "John Doe" },
{ "id": 2, "name": "Jane Smith" }
]

POST /users:
Creates a new user.

{
"name": "New User"
}

GET /users/1:
Retrieves the user with ID
1.

{
"id": 1, "name": "John Doe"
}

PUT /users/1:
Updates the user with ID
1 .

{
"name": "Updated User"
}

DELETE /users/1:
Deletes the user with ID
1.

Example in Node.js (Express) and React


Here's a quick example of a REST API in Node.js using Express and how it might be consumed in a React app.

Node.js (Express) REST API


server.js:

const express = require('express');


const app = express();
const bodyParser = require('body-parser');
const PORT = 5000;

WE Notes Unit - III,IV Complete (R-18) 2


app.use(bodyParser.json());

let users = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' }
];

app.get('/users', (req, res) => {


res.json(users);
});

app.post('/users', (req, res) => {


const newUser = { id: users.length + 1, ...req.body };
users.push(newUser);
res.status(201).json(newUser);
});

app.get('/users/:id', (req, res) => {


const user = users.find(u => u.id == req.params.id);
if (user) {
res.json(user);
} else {
res.status(404).send('User not found');
}
});

app.put('/users/:id', (req, res) => {


const user = users.find(u => u.id == req.params.id);
if (user) {
Object.assign(user, req.body);
res.json(user);
} else {
res.status(404).send('User not found');
}
});

app.delete('/users/:id', (req, res) => {


users = users.filter(u => u.id != req.params.id);
res.status(204).send();
});

app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});

React Application
App.js:

WE Notes Unit - III,IV Complete (R-18) 3


import React, { useState, useEffect } from 'react';
import axios from 'axios';

function App() {
const [users, setUsers] = useState([]);

useEffect(() => {
axios.get('http://localhost:5000/users')
.then(response => setUsers(response.data))
.catch(error => console.error(error));
}, []);

const addUser = (name) => {


axios.post('http://localhost:5000/users', { name })
.then(response => setUsers([...users, response.data]))
.catch(error => console.error(error));
};

const updateUser = (id, name) => {


axios.put(`http://localhost:5000/users/${id}`, { name })
.then(response => setUsers(users.map(user => user.id === id ? response.dat
a : user)))
.catch(error => console.error(error));
};

const deleteUser = (id) => {


axios.delete(`http://localhost:5000/users/${id}`)
.then(() => setUsers(users.filter(user => user.id !== id)))
.catch(error => console.error(error));
};

return (
<div className="App">
<h1>User Management</h1>
<ul>
{users.map(user => (
<li key={user.id}>
{user.name}
<button onClick={() => updateUser(user.id, 'Updated Name')}>Update</
button>
<button onClick={() => deleteUser(user.id)}>Delete</button>
</li>
))}
</ul>
<button onClick={() => addUser('New User')}>Add User</button>
</div>
);
}

export default App;

WE Notes Unit - III,IV Complete (R-18) 4


This example demonstrates how a simple REST API can be built using Node.js and how it can be consumed in a React
application to perform CRUD operations.

Q2. Introduction to express, Installation of express and simple express


application
A.)

Introduction to Express
Express is a minimal and flexible Node.js web application framework that provides a robust set of features to build web and
mobile applications. It facilitates the rapid development of Node-based web applications. With Express, you can manage
different HTTP requests at different URLs and create routes for your web application.

Key Features of Express:


Robust routing: Defines a routing table to perform different actions based on HTTP method and URL.

HTTP helpers: Facilitates handling redirection, caching, etc.

Middleware support: Provides a series of middleware functions that can be used to handle requests.

View system: Integrates with various template engines to generate responses.

Installation of Express
Before installing Express, ensure you have Node.js and npm (Node Package Manager) installed on your machine. You can
download them from nodejs.org.

Steps to Install Express:


1. Create a new project directory:

mkdir express-app
cd express-app

2. Initialize a new Node.js project:

npm init -y

This command will create a package.json file with default settings.

3. Install Express:

npm install express --save

The --save flag adds Express to the dependencies in the package.json file.

Simple Express Application


Let's create a simple Express application that responds with "Hello, World!" when accessed.

Steps to Create the Application:


1. Create a file named app.js :

touch app.js

WE Notes Unit - III,IV Complete (R-18) 5


2. Write the following code in app.js :

const express = require('express');


const app = express();
const port = 3000;

// Define a route for the root URL ("/")


app.get('/', (req, res) => {
res.send('Hello, World!');
});

// Start the server and listen on the specified port


app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});

3. Run the application:

node app.js

4. Access the application:


Open your browser and navigate to
http://localhost:3000 . You should see "Hello, World!" displayed on the page.

Explanation of the Code


Import Express:

const express = require('express');

This line imports the Express module.

Create an Express Application:

const app = express();

This line initializes the Express application.

Define a Route:

app.get('/', (req, res) => {


res.send('Hello, World!');

This line sets up a route for the root URL ( / ). When a GET request is made to this URL, the server responds with
"Hello, World!".

Start the Server:

app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});

This line starts the server and makes it listen on port 3000. When the server is ready, it logs a message to the console.

WE Notes Unit - III,IV Complete (R-18) 6


Conclusion
Express simplifies the process of creating server-side applications with Node.js. By following the steps outlined above, you
can install Express and create a basic web server that responds to HTTP requests. This forms the foundation for building
more complex web applications.

Q3. Application, request & response objects configuring an express application


A.)

Express Application, Request, and Response Objects


In Express, the application, request, and response objects are fundamental components that facilitate the creation of web
applications.

1. Application Object ( app )


The application object in Express is an instance of the Express application that you create using express() . It serves as the
central part of your web application, where you define routes, middleware, configuration, and other settings.

Creating an Application:

const express = require('express');


const app = express();

Defining Routes:
You can define various routes using the
app object:

app.get('/', (req, res) => {


res.send('Hello, World!');
});

Starting the Server:

app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});

2. Request Object ( req )


The request object represents the HTTP request and contains properties for the request query string, parameters, body, HTTP
headers, and more.

Accessing Request Data:

app.get('/user/:id', (req, res) => {


console.log(req.params.id); // Accessing route parameters
console.log(req.query.name); // Accessing query parameters
res.send(`User ID: ${req.params.id}`);
});

req.params : Contains route parameters (e.g., :id in /user/:id ).

WE Notes Unit - III,IV Complete (R-18) 7


req.query : Contains query string parameters (e.g., ?name=John ).

req.body : Contains body data (requires body-parsing middleware).

3. Response Object ( res )


The response object represents the HTTP response that an Express app sends when it gets an HTTP request.

Sending a Response:

app.get('/', (req, res) => {


res.send('Hello, World!');
});

res.send() : Sends a string or object as an HTTP response.

res.json() : Sends a JSON response.

res.status() : Sets the HTTP status for the response.

Configuring an Express Application

Middleware
Middleware functions are functions that have access to the request and response objects and can modify them. Middleware
can execute code, make changes to the request and response objects, end the request-response cycle, and call the next
middleware function in the stack.

Using Middleware:

const express = require('express');


const app = express();

// Custom middleware
app.use((req, res, next) => {
console.log('Request URL:', req.originalUrl);
next();
});

app.get('/', (req, res) => {


res.send('Hello, World!');
});

app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});

Body Parsing
To handle incoming request bodies, especially for POST and PUT requests, you need to use body-parsing middleware like
body-parser (though in recent versions of Express, body-parser is included in Express).

Using Body-Parser:

npm install body-parser

WE Notes Unit - III,IV Complete (R-18) 8


const express = require('express');
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.json());

app.post('/user', (req, res) => {


console.log(req.body); // Accessing parsed body data
res.send('User data received');
});

app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});

Q4. Render View in Express


A.) Rendering views in Express involves using template engines to generate HTML pages dynamically based on the data
passed to them. This is a common pattern in web applications where the server generates HTML content and sends it to
the client's browser.

Steps to Render Views in Express


1. Set Up a Template Engine:
Express supports various template engines like Pug (formerly Jade), EJS, Handlebars, etc. For this example, we’ll
use EJS (Embedded JavaScript).

2. Install the Template Engine:


Install EJS using npm:

npm install ejs

3. Configure the Template Engine in Express:


Configure Express to use EJS as the template engine and set the directory for the views.

4. Create View Templates:


Create EJS templates that will be rendered by Express.

5. Render Views:
Use the
res.render() method to render a view and send the resulting HTML to the client.

Example: Rendering Views with EJS

1. Set Up the Project


Create a new directory for your project and initialize it:

mkdir express-view-app
cd express-view-app
npm init -y

Install Express and EJS:

WE Notes Unit - III,IV Complete (R-18) 9


npm install express ejs

2. Configure Express to Use EJS


Create a file named server.js and configure Express to use EJS:

const express = require('express');


const app = express();
const PORT = 3000;

// Set the view engine to EJS


app.set('view engine', 'ejs');

// Set the directory for the views


app.set('views', './views');

// Define a route that renders an EJS view


app.get('/', (req, res) => {
res.render('index', { title: 'Welcome', message: 'Hello, World!' });
});

// Start the server


app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

3. Create View Templates


Create a views directory in the project root and add an index.ejs file:

express-view-app/
├── views/
│ └── index.ejs
├── server.js
└── package.json

views/index.ejs:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %></title>
</head>
<body>
<h1><%= message %></h1>
</body>
</html>

WE Notes Unit - III,IV Complete (R-18) 10


4. Run the Application
Run the server using Node.js:

node server.js

Navigate to http://localhost:3000 in your browser. You should see a web page with the title "Welcome" and the
message "Hello, World!".

Explanation
Setting the View Engine:

app.set('view engine', 'ejs');

This line tells Express to use EJS as the template engine.

Setting the Views Directory:

app.set('views', './views');

This line sets the directory where your view templates are located.

Rendering a View:

app.get('/', (req, res) => {


res.render('index', { title: 'Welcome', message: 'Hello, World!' });
});

The res.render() method renders the index.ejs template, passing in an object with the data to be used in the
template. The keys in the object ( title and message ) correspond to the placeholders in the EJS template ( <%=
title %> and <%= message %> ).

Using Dynamic Data


You can render views with dynamic data by passing variables to the res.render() method. Here’s an example with a list
of items:
server.js:

const express = require('express');


const app = express();
const PORT = 3000;

app.set('view engine', 'ejs');


app.set('views', './views');

app.get('/', (req, res) => {


const items = ['Item 1', 'Item 2', 'Item 3'];
res.render('index', { title: 'Item List', items });
});

app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

WE Notes Unit - III,IV Complete (R-18) 11


views/index.ejs:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %></title>
</head>
<body>
<h1><%= title %></h1>
<ul>
<% items.forEach(item => { %>
<li><%= item %></li>
<% }) %>
</ul>
</body>
</html>

In this example, an array of items is passed to the index.ejs template and rendered as an unordered list.

Conclusion
Rendering views in Express using a template engine like EJS allows you to dynamically generate HTML content based
on data from your application. This approach is beneficial for creating dynamic web pages and separating the logic of
your application from the presentation.

Q5. Explain Authentication & Authorization? Explain a way on how we can


secure an endpoint using JWT?
A.)

Authentication
Authentication is the process of verifying the identity of a user or system. It ensures that the entity trying to access a resource
or perform an action is who or what it claims to be. In web applications, authentication typically involves users providing
credentials (such as username and password) to prove their identity.

Authorization
Authorization, on the other hand, is the process of determining whether an authenticated user has the necessary permissions
to access a particular resource or perform a specific action. Once a user's identity has been verified through authentication,
authorization ensures that the user only has access to the resources and functionalities that they are allowed to use.

Securing Endpoints with JWT (JSON Web Tokens)


JSON Web Tokens (JWT) provide a method for securely transmitting information between parties as a JSON object. They
can be used as a means of authentication and authorization in web applications. Here's how you can secure endpoints with
JWT:

1. Authentication:

When a user successfully logs in, generate a JWT token containing the user's ID and any additional relevant
information.

WE Notes Unit - III,IV Complete (R-18) 12


Sign the token using a secret key known only to the server.

Send the JWT token back to the client.

2. Authorization:

For protected endpoints, require clients to include the JWT token in the request headers.

On the server side, verify the JWT token's signature using the secret key.

If the token is valid, extract the user's ID and any other relevant information from the token.

Use the extracted information to determine whether the user is authorized to access the requested resource or
perform the requested action.

3. Middleware:

Implement middleware in your Express application to handle JWT verification and user authentication.

Verify the JWT token in the request headers using the secret key.

If the token is valid, extract the user's information and attach it to the request object.

If the token is invalid or missing, return an error response.

4. Example Implementation:

import express from 'express';


import jwt from 'jsonwebtoken';

const app = express();


const SECRET_KEY = 'your_secret_key';

// Middleware to verify JWT token


function verifyToken(req, res, next) {
const token = req.headers['authorization'];

if (!token) {
return res.status(401).json({ message: 'Unauthorized' });
}

jwt.verify(token, SECRET_KEY, (err, decoded) => {


if (err) {
return res.status(403).json({ message: 'Invalid token' });
}

req.user = decoded;
next();
});
}

// Login route
app.post('/login', (req, res) => {
// Check user credentials
const user = { id: 1, username: 'user1' };
const token = jwt.sign(user, SECRET_KEY);
res.json({ token });
});

WE Notes Unit - III,IV Complete (R-18) 13


// Protected route
app.get('/protected', verifyToken, (req, res) => {
res.json({ message: 'Protected endpoint', user: req.user });
});

// Start the server


app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});

In this example, the /login route generates a JWT token upon successful authentication. The /protected route is protected
using the verifyToken middleware, which verifies the JWT token included in the request headers.

Conclusion
Authentication and authorization are essential for ensuring the security of web applications. By using JWT tokens, you can
securely authenticate users and authorize access to protected endpoints in your Express application. This helps prevent
unauthorized access to sensitive resources and functionalities.

Q6 . What is Type Script? Explain its compiler Options, Classes and Interfaces.
A.) TypeScript is an open-source programming language developed and maintained by Microsoft. It is a superset of
JavaScript, meaning that any valid JavaScript code is also valid TypeScript code. TypeScript extends JavaScript by adding
static typing, which allows developers to specify types for variables, function parameters, return values, and more.

Key Features of TypeScript:


1. Static Typing: TypeScript introduces static typing, enabling developers to catch type-related errors at compile time
rather than runtime. This helps in identifying potential bugs early in the development process.

2. Enhanced Tooling: TypeScript provides better tooling support compared to JavaScript. Integrated development
environments (IDEs) and code editors can leverage TypeScript's type information for features like autocompletion,
refactoring, and code navigation.

3. Modern ECMAScript Features: TypeScript supports the latest ECMAScript features, allowing developers to write
code using modern JavaScript syntax (e.g., arrow functions, async/await) while maintaining compatibility with older
JavaScript environments through transpilation.

4. Interfaces and Classes: TypeScript supports object-oriented programming features such as interfaces and classes,
providing a way to define contracts and blueprints for objects. Interfaces enable structural typing, while classes enable
classical inheritance and encapsulation.

5. Enums and Generics: TypeScript includes support for enumerations (enums) and generics. Enums allow developers to
define a set of named constants, while generics enable the creation of reusable components that can work with a variety
of data types.

6. Type Inference: TypeScript's type inference system automatically infers the types of variables based on their usage. This
reduces the need for explicit type annotations, making code cleaner and more concise.

7. Union Types and Intersection Types: TypeScript allows the creation of union types and intersection types, providing
flexibility in defining complex type relationships. Union types allow a value to have multiple possible types, while
intersection types combine multiple types into a single type.

WE Notes Unit - III,IV Complete (R-18) 14


8. Decorators: TypeScript supports decorators, which are a form of metadata that can be attached to classes, methods, or
properties. Decorators are commonly used in frameworks like Angular for adding metadata and behavior to components.

Benefits of Using TypeScript:


Improved Code Quality: Static typing helps in catching errors early and ensuring code correctness.

Enhanced Developer Productivity: Features like autocompletion and type checking in IDEs improve developer
productivity and reduce debugging time.

Maintainability: TypeScript's type system facilitates better code organization and documentation, making codebases
easier to understand and maintain.

Scalability: TypeScript is well-suited for large-scale applications due to its support for modules, interfaces, and classes,
which promote code reuse and modularity.

1. TypeScript Compiler Options


Compiler options in TypeScript provide a way to configure how the TypeScript compiler ( tsc ) behaves when it compiles
TypeScript code to JavaScript. These options can be specified in a tsconfig.json file or passed directly to the compiler via
the command line.
Some commonly used compiler options include:

target: Specifies the ECMAScript target version for the compiled JavaScript code (e.g., ES5, ES6).

module: Specifies the module code generation (e.g., CommonJS, AMD, ES6 modules).

outDir: Specifies the output directory for compiled JavaScript files.

strict: Enables strict type-checking options.

noImplicitAny: Raises an error when a variable is declared without an explicit type.

esModuleInterop: Enables compatibility with modules using export = syntax.

An example tsconfig.json file:

{
"compilerOptions": {
"target": "ES6",
"module": "CommonJS",
"outDir": "./dist",
"strict": true,
"noImplicitAny": true,
"esModuleInterop": true}
}

2. Classes in TypeScript
Classes in TypeScript allow you to define blueprints for objects with properties and methods. They enable you to implement
object-oriented programming concepts such as inheritance, encapsulation, and abstraction.
Syntax:

class ClassName {
// Properties
property1: type;
property2: type;

WE Notes Unit - III,IV Complete (R-18) 15


// Constructor
constructor(parameter1: type, parameter2: type) {
this.property1 = parameter1;
this.property2 = parameter2;
}

// Methods
method1(): returnType {
// Method body
}

method2(): returnType {
// Method body
}
}

Example:

class Person {
firstName: string;
lastName: string;

constructor(firstName: string, lastName: string) {


this.firstName = firstName;
this.lastName = lastName;
}

getFullName(): string {
return `${this.firstName} ${this.lastName}`;
}
}

const person1 = new Person('John', 'Doe');


console.log(person1.getFullName()); // Output: John Do

3. Interfaces in TypeScript
Interfaces in TypeScript define contracts for objects, specifying the structure and types of their properties and methods. They
allow you to enforce consistency and provide type-checking capabilities.
Syntax:

interface InterfaceName {
property1: type;
property2: type;

method1(): returnType;
method2(): returnType;
}

Example:

WE Notes Unit - III,IV Complete (R-18) 16


interface Shape {
color: string;
area(): number;
}

class Circle implements Shape {


color: string;
radius: number;

constructor(color: string, radius: number) {


this.color = color;
this.radius = radius;
}

area(): number {
return Math.PI * this.radius ** 2;
}
}

const circle1 = new Circle('red', 5);


console.log(circle1.area()); // Output: 78.53981633974483

Interfaces can also be used to define contracts for function types, arrays, and more complex structures.

Conclusion
TypeScript compiler options allow you to configure the behavior of the TypeScript compiler. Classes enable you to define
blueprints for objects with properties and methods, while interfaces define contracts for objects, specifying their structure
and types. These features help you write maintainable, scalable, and type-safe code in TypeScript.

Q6. Explain about TypeScript Generic and Decorators along with example?
A.)

TypeScript Generics
TypeScript generics provide a way to create reusable components that can work with a variety of data types while
maintaining type safety. Generics allow you to define functions, classes, and interfaces that can operate on any type, rather
than a specific one.

Syntax:

function functionName<T>(arg: T): T {


// Function body
}

class ClassName<T> {
// Class body
}

interface InterfaceName<T> {

WE Notes Unit - III,IV Complete (R-18) 17


// Interface body
}

Example:

function identity<T>(arg: T): T {


return arg;
}

// Using generics
let result1 = identity<string>('Hello');
let result2 = identity<number>(123);

In this example, the identity function is a generic function that takes an argument of type T and returns the same type. The
type T is specified when calling the function.

TypeScript Decorators
Decorators are a feature of TypeScript that allow you to attach metadata and modify the behavior of classes, methods,
properties, or at design time. They provide a way to add functionality to existing code without modifying its underlying
structure.

Syntax:

function decoratorName(target: any, key: string): void {


// Decorator implementation
}

@decoratorName
class ClassName {
@decoratorName
propertyName: type;

@decoratorName
methodName() {
// Method body
}
}

Example:

function log(target: any, key: string): void {


console.log(`Method ${key} is called`);
}

class Example {
@log
greet() {
console.log('Hello, world!');
}

WE Notes Unit - III,IV Complete (R-18) 18


}

const example = new Example();


example.greet(); // Output: Method greet is called

In this example, the log decorator is applied to the greet method of the Example class. When the greet method is called,
the decorator logs a message to the console.

Conclusion
TypeScript generics and decorators are powerful features that enhance the flexibility and expressiveness of the language.
Generics enable you to create reusable components that work with different data types, while decorators provide a way to
add metadata and behavior to classes and their members at design time. These features are widely used in TypeScript
libraries and frameworks to build scalable and maintainable codebases.

Unit - IV (Angular 2)

Q1. Difference between Angular 1 vs Angular 2


A.)

WE Notes Unit - III,IV Complete (R-18) 19


Q2. Give an introduction about Angular 2 as well as to its architecture
A.)
Angular 2, now commonly known as Angular, is a popular open-source front-end web application framework maintained by
Google and a community of developers. It is a complete rewrite of AngularJS (Angular 1.x) and offers a modern approach to
building web applications with a focus on speed, performance, and developer productivity.

Introduction to Angular:
1. Component-Based Architecture:
Angular adopts a component-based architecture, where applications are built using reusable and composable
components. Components encapsulate HTML templates, CSS styles, and behavior logic, making it easier to manage and
maintain complex user interfaces.

2. Typescript Language:
Angular is written in TypeScript, a superset of JavaScript that adds static typing, classes, interfaces, and other features to
JavaScript. TypeScript enhances developer productivity, improves code maintainability, and provides better tooling
support.

3. Modular Development:
Angular applications are organized into modules, which are collections of related components, directives, pipes, and
services. Modular development promotes code reusability, separation of concerns, and scalability.

4. Two-Way Data Binding:


Angular provides two-way data binding, which automatically synchronizes the model state with the view and vice versa.
Changes in the model are reflected in the view, and user interactions in the view update the model accordingly.

5. Dependency Injection:
Angular's dependency injection system facilitates the creation and management of application dependencies. It promotes
loosely coupled and highly testable code by allowing components and services to declare their dependencies rather than
creating them directly.

6. Routing and Navigation:


Angular includes a powerful router that enables single-page application (SPA) navigation. It supports client-side routing,
lazy loading of modules, route guards, and nested routing configurations.

7. HTTP Client:
Angular provides an HTTP client module for making HTTP requests to backend servers. It offers features such as
request and response interception, error handling, and support for RxJS Observables.

8. Forms and Validation:


Angular offers robust support for building forms and implementing client-side validation. It provides two form-building
approaches: template-driven forms and reactive forms (also known as model-driven forms), each suitable for different
use cases.

Angular Architecture:

WE Notes Unit - III,IV Complete (R-18) 20


Angular applications follow a modular and hierarchical architecture, consisting of the following key components:

1. Modules:
Angular applications are organized into modules, which are logical containers for components, directives, pipes, and
services. Modules help in organizing the application's features and dependencies.

2. Components:
Components are the building blocks of Angular applications. Each component encapsulates a part of the user interface,
consisting of an HTML template, CSS styles, and TypeScript code that defines its behavior.

3. Templates:
Templates define the HTML structure of Angular components and include bindings, directives, and event handlers that
connect the component's data and behavior with the view.

4. Directives:
Directives are custom HTML attributes, elements, or structural markers that extend the behavior of HTML elements.
Angular provides built-in directives like ngIf, ngFor, and ngModel, as well as the ability to create custom directives.

5. Services:
Services are reusable business logic units that perform specific tasks, such as fetching data from a server, performing
calculations, or managing application state. Services promote code reusability and maintainability.

6. Dependency Injection (DI):


Angular's dependency injection system manages the creation and injection of dependencies into components, directives,
and services. DI promotes loose coupling and facilitates unit testing.

7. Routing and Navigation:


Angular's router enables navigation between different views or components within a single-page application. It supports
route definitions, route parameters, route guards, lazy loading, and nested routing configurations.

8. HTTP Client:
Angular's HTTP client module provides a way to communicate with backend servers using HTTP requests. It supports
features such as request and response interception, error handling, and asynchronous data handling with RxJS
Observables.

WE Notes Unit - III,IV Complete (R-18) 21


Q3. Explain about angular routing, Passing data from parent to child and
passing between siblings along with example
A.)

Angular Routing:
Angular's router is a powerful feature that allows you to navigate between different views or components within a single-
page application (SPA). It enables you to define routes, load components dynamically, and handle navigation events.

1. Setting Up Routing:
To use Angular's router, you need to import the RouterModule and define routes in your application module. Each route is
associated with a component and a path.

import { RouterModule, Routes } from '@angular/router';


import { HomeComponent } from './home.component';
import { AboutComponent } from './about.component';

const routes: Routes = [


{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent }
];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule

2. Router Outlet:
In your main application component template, use the <router-outlet></router-outlet> directive to specify where Angular
should render the component associated with the current route.

<router-outlet></router-outlet>

3. Navigating Between Routes:


You can navigate between routes programmatically using the Router service or by using the routerLink directive in
templates.

<a routerLink="/">Home</a>
<a routerLink="/about">About</a>

Passing Data Between Parent and Child Components:


In Angular, you can pass data from a parent component to a child component using Input properties.

1. Parent Component:
Define a property in the parent component and bind it to an input property in the child component.

WE Notes Unit - III,IV Complete (R-18) 22


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

@Component({
selector: 'app-parent',
template: `
<app-child [message]="parentMessage"></app-child>
`
})
export class ParentComponent {
parentMessage = 'Message from parent';
}

2. Child Component:
Declare an input property in the child component to receive data from the parent component.

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

@Component({
selector: 'app-child',
template: `
<p>{{ message }}</p>
`
})
export class ChildComponent {
@Input() message: string;
}

Passing Data Between Sibling Components:


To pass data between sibling components, you can use a shared service or a parent component as an intermediary.

Using Shared Service:


1. Create a shared service to store and manage shared data.

2. Inject the service into both sibling components.

3. Use the service to pass data between the components.

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

@Injectable()
export class DataService {
sharedData: string;

setData(data: string) {
this.sharedData = data;
}

getData() {
return this.sharedData;

WE Notes Unit - III,IV Complete (R-18) 23


}
}

Using Parent Component:


1. Pass data from the parent component to both sibling components using input properties and output events.

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

@Component({
selector: 'app-parent',
template: `
<app-sibling1 [data]="sharedData"></app-sibling1>
<app-sibling2 [data]="sharedData"></app-sibling2>
`
})
export class ParentComponent {
sharedData = 'Shared data';
}

Conclusion:
Angular routing allows you to navigate between different views or components within a single-page application. You can
pass data between parent and child components using input properties, and between sibling components using a shared
service or a parent component as an intermediary. These techniques enable you to create more dynamic and interactive
Angular applications.

Q4. Explain about Angular 2 Directives, Modules & Components


A.) In Angular 2 (and later versions), directives, modules, and components are fundamental building blocks that enable you
to create dynamic and modular applications. Let's explore each of these concepts:

1. Directives:
Directives are markers on a DOM element that tell Angular to do something with that element or its children. They are
classified into three types:

i. Component Directives:
Component directives are directives with a template. They represent a UI component and encapsulate its behavior,
presentation, and structure in a single reusable unit. Components are the most commonly used directive type in Angular
applications.

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

@Component({
selector: 'app-example',
template: '<h1>Hello, World!</h1>'
})
export class ExampleComponent {}

ii. Structural Directives:

WE Notes Unit - III,IV Complete (R-18) 24


Structural directives alter the DOM layout by adding, removing, or manipulating elements based on conditionals such as
*ngIf and *ngFor .

<div *ngIf="isVisible">Visible Content</div>


<ul>
<li *ngFor="let item of items">{{ item }}</li>
</ul>

iii. Attribute Directives:


Attribute directives change the appearance or behavior of an element, component, or another directive. They typically listen
for and respond to events.

<input type="text" appCustomDirective />

2. Modules:
Modules in Angular are containers for a group of related components, directives, pipes, and services. They help organize and
manage the application's components and services into cohesive blocks with well-defined boundaries.

i. Root Module (AppModule):


The root module, typically named AppModule , is the starting point of an Angular application. It bootstraps the application and
imports other modules.

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


import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

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

ii. Feature Modules:


Feature modules are used to organize application functionality into cohesive blocks. They can be imported into the root
module or other feature modules.

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


import { CommonModule } from '@angular/common';
import { FeatureComponent } from './feature.component';

@NgModule({
declarations: [FeatureComponent],
imports: [CommonModule],
exports: [FeatureComponent]

WE Notes Unit - III,IV Complete (R-18) 25


})
export class FeatureModule {

3. Components:
Components are the basic building blocks of Angular applications. They encapsulate the UI (HTML template), the
application logic (Typescript class), and the styling (CSS) into reusable and modular units.

i. Creating a Component:

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

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

ii. Template and Data Binding:


Components use data binding to communicate between the component class (Typescript) and the component template
(HTML).

<!-- example.component.html -->


<h1>{{ title }}</h1>
<button (click)="onClick()">Click Me</button>

// example.component.ts
import { Component } from '@angular/core';

@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css']
})
export class ExampleComponent {
title = 'Example Component';

onClick(): void {
console.log('Button clicked');
}
}

iii. Lifecycle Hooks:


Angular components have a lifecycle managed by Angular itself. You can tap into these lifecycle events using lifecycle
hooks to perform certain actions at specific points in the component's lifecycle.

typescriptCopy code
import { Component, OnInit, OnDestroy } from '@angular/core';

WE Notes Unit - III,IV Complete (R-18) 26


@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit, OnDestroy {
ngOnInit(): void {
// Called after the constructor
}

ngOnDestroy(): void {
// Called just before Angular destroys the component
}
}

Conclusion:
In Angular, directives, modules, and components are essential concepts that enable you to create dynamic, modular, and
maintainable applications. Directives allow you to extend HTML functionality, modules provide a way to organize and
manage application functionality, and components encapsulate UI elements and application logic into reusable units.
Understanding these concepts is crucial for building effective Angular applications.

Q5. Angular Services & Consuming API


A.) In Angular, services are a way to organize and share code across components. They are used to encapsulate reusable
functionality that doesn't belong in a specific component, such as data manipulation, API calls, or shared utilities. Here's how
you can create and consume services in Angular to consume APIs:

Creating a Service:
1. Generate a Service:
You can use the Angular CLI to generate a service.

ng generate service my-service

2. Define Service Logic:


Implement the functionality you need in the service class. For example, making an HTTP request to consume an API.

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


import { HttpClient } from '@angular/common/http';
import { Obervable } from 'rxjs';

@Injectable({
providedIn: 'root'
})
export class MyService {
constructor(private http: HttpClient) {}

fetchData(): Observable<any> {
return this.http.get('https://api.example.com/data');

WE Notes Unit - III,IV Complete (R-18) 27


}
}

Consuming the Service:


1. Inject the Service:
Inject the service into the component where you want to use it.

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.myService.fetchData().subscribe(data => {
this.data = data;
});
}
}

2. Use Service Methods:


Call the service method in the component and handle the response.

<div *ngIf="data">
<p>Data: {{ data | json }}</p>
</div>

Handling Asynchronous Data:


Since API requests are asynchronous, it's important to handle them appropriately. In the above example, we subscribe to the
Observable returned by the fetchData() method. When the data arrives, the subscribe callback function is called, and we
assign the received data to a component property ( data in this case).

Error Handling:
Always handle errors when consuming APIs. You can use the subscribe method's second argument to define an error
handler.

this.myService.fetchData().subscribe(
data => {
// Handle data
},
error => {
console.error('Error fetching data:', error);

WE Notes Unit - III,IV Complete (R-18) 28


}
);

Conclusion:
Angular services are powerful tools for organizing and sharing code in your application. They allow you to encapsulate
functionality in a reusable way, making your application more modular and maintainable. When consuming APIs, services
play a crucial role in making HTTP requests and handling data, ensuring that your application interacts effectively with
external data sources.

Q6. Explain about Angular Observable & Binding


A.)

Angular Observables:
Observables are a core part of Angular's reactive programming paradigm. They represent a sequence of asynchronous data or
events over time. Observables can emit multiple values asynchronously, and they provide a wide range of operators to
transform, combine, and manipulate these data streams.

Creating Observables:
You can create observables using the Observable class from the rxjs library. There are various ways to create observables,
such as:

1. From a Static Value:

import { Observable } from 'rxjs';

const observable = new Observable(observer => {


observer.next('Hello');
observer.complete();
});

2. From an Array or Iterable:

import { of } from 'rxjs';


const observable = of(1, 2, 3)

3. From an Event:

import { fromEvent } from 'rxjs';


const observable = fromEvent(document, 'click');

Subscribing to Observables:
You subscribe to observables to listen for values emitted by the observable. The subscribe() method allows you to define
callbacks for handling emitted values, errors, and completion notifications.

observable.subscribe(
value => console.log(value), // onNext
error => console.error(error), // onError

WE Notes Unit - III,IV Complete (R-18) 29


() => console.log('Complete') // onComplete
);

Operators:
Observables provide a rich set of operators for transforming, filtering, and combining data streams. Some commonly used
operators include map , filter , mergeMap , switchMap , and debounceTime .

typescriptCopy code
import { from } from 'rxjs';
import { filter, map } from 'rxjs/operators';

from([1, 2, 3, 4, 5])
.pipe(
filter(value => value % 2 === 0),
map(value => value * 2)
)
.subscribe(value => console.log(value));

Angular Data Binding:


Data binding is a fundamental feature of Angular that allows you to establish a connection between the component's data and
the HTML template. It enables you to display data dynamically in the view and respond to user interactions.

Interpolation:
Interpolation allows you to embed expressions into the HTML template. It is denoted by double curly braces {{ }} .

<p>{{ message }}</p>

Property Binding:
Property binding allows you to set an element's property to a value of a component's property. It is denoted by square
brackets [ ] .

<img [src]="imageUrl">

Event Binding:
Event binding allows you to listen for and respond to DOM events. It is denoted by parentheses ( ) .

<button (click)="handleClick()">Click Me</button>

Two-Way Data Binding:


Two-way data binding allows you to bind a component property to an input element and listen for changes in both directions.
It is achieved using the ngModel directive with banana-in-a-box syntax [(ngModel)] .

<input [(ngModel)]="username">

Conclusion:

WE Notes Unit - III,IV Complete (R-18) 30


Observables and data binding are crucial concepts in Angular for building reactive and dynamic web applications.
Observables enable you to work with asynchronous data streams and handle events in a functional and declarative manner.
Data binding allows you to establish a connection between the component's data and the HTML template, enabling dynamic
rendering and user interaction. Understanding and effectively using observables and data binding are essential skills for
Angular developers to create modern and responsive applications.

Q7. Explain about Types of forms in Angular?


A.) In Angular, there are two main types of forms: Template-driven forms and Reactive forms. Each type has its own
advantages and use cases. Let's explore each type:

1. Template-Driven Forms:
Template-driven forms are simpler to implement and are suitable for scenarios where forms are relatively straightforward and
the data binding is primarily one-way (from the component class to the template).

Features:
Form logic is defined directly in the HTML template.

Uses Angular directives such as ngModel , ngForm , and ngSubmit .

Automatic synchronization between form controls and component properties.

Minimal component class code.

Example:

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


<input type="text" name="username" [(ngModel)]="user.username" required>
<input type="email" name="email" [(ngModel)]="user.email" required>
<button type="submit">Submit</button>
</form>

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

@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponent {
user = {
username: '',
email: ''
};

onSubmit(form: any) {
console.log('Form submitted!', form.value);
}
}

2. Reactive Forms:

WE Notes Unit - III,IV Complete (R-18) 31


Reactive forms provide a more flexible and robust way to handle complex form scenarios. They are suitable for scenarios
where forms are dynamic, have complex validation requirements, or require extensive form control manipulation.

Features:
Form logic is defined programmatically in the component class.

Uses FormGroup , FormControl , and FormBuilder classes from @angular/forms module.

Full control over form validation and error handling.

Dynamic forms and form controls manipulation.

Example:

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">


<input type="text" formControlName="username" required>
<input type="email" formControlName="email" required>
<button type="submit">Submit</button>
</form>

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


import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponent implements OnInit {
myForm: FormGroup;

constructor(private formBuilder: FormBuilder) {}

ngOnInit(): void {
this.myForm = this.formBuilder.group({
username: ['', Validators.required],
email: ['', [Validators.required, Validators.email]]
});
}

onSubmit() {
console.log('Form submitted!', this.myForm.value);
}
}

Comparison:
Feature Template-Driven Forms Reactive Forms

Ease of Use Simple More Complex

Form Logic Template HTML Component Class

Two-Way Data Binding Yes No

WE Notes Unit - III,IV Complete (R-18) 32


Dynamic Form Controls Limited Flexible

Control Over Validation Limited Extensive

Testability Limited Easier

Conclusion:
Both template-driven forms and reactive forms have their place in Angular development, and the choice between them
depends on the specific requirements of your application. Template-driven forms are simpler and more suitable for basic
forms with minimal validation requirements, while reactive forms provide more control and flexibility for complex forms
with dynamic behavior and extensive validation. Understanding the differences between these two types of forms allows you
to choose the appropriate approach for your Angular applications.

Q8. Explain about pipes in Angular?


A.) In Angular, pipes are a feature that allows you to transform data in your templates before displaying it. They are similar
to filters in AngularJS or filters in Vue.js, and they help you format data for presentation in a clean and declarative way.
Angular provides several built-in pipes for common data transformations, and you can also create custom pipes to suit your
specific needs.

Built-in Pipes:
Angular comes with a variety of built-in pipes that you can use out of the box. Some of the commonly used built-in pipes
include:

1. DatePipe: Formats dates according to the locale rules.

<p>{{ today | date }}</p> <!-- Outputs: Mar 15, 2022 -->

2. UpperCasePipe and LowerCasePipe: Converts strings to uppercase or lowercase.

<p>{{ 'Hello World' | uppercase }}</p> <!-- Outputs: HELLO WORLD -->
<p>{{ 'Hello World' | lowercase }}</p> <!-- Outputs: hello world -->

3. CurrencyPipe: Formats numbers as currency strings according to locale rules.

<p>{{ price | currency }}</p> <!-- Otputs: $123.45 -->

4. DecimalPipe: Formats numbers as decimal strings.

<p>{{ pi | number:'1.2-2' }}</p> <!-- Outputs: 3.14 -->

5. PercentPipe: Formats numbers as percentage strings.

<p>{{ ratio | percent }}</p> <!-- Outputs: 0.5% -->

Chaining Pipes:
You can chain multiple pipes together to perform complex data transformations.

<p>{{ birthday | date | uppercase }}</p> <!-- Outputs: MARCH 15, 2022 -->

WE Notes Unit - III,IV Complete (R-18) 33


Custom Pipes:
You can also create custom pipes to perform custom data transformations that are not covered by the built-in pipes. To create
a custom pipe, you need to implement the PipeTransform interface and define the transformation logic in the transform
method.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'custom' })


export class CustomPipe implements PipeTransform {
transform(value: any, ...args: any[]): any {
// Transformation logic
return transformedValue;
}
}

You can then use the custom pipe in your templates just like built-in pipes.

<p>{{ data | custom }}</p>

Pure vs Impure Pipes:


By default, Angular pipes are pure, meaning they are stateless and their output depends only on their input. However, you
can make a pipe impure by setting the pure property to false in the @Pipe decorator. Impure pipes are recalculated on
every change detection cycle, which can impact performance.

@Pipe({
name: 'myPipe',
pure: false
})
export class MyPipe implements PipeTransform {
// Pipe implementation
}

Conclusion:
Pipes are a powerful feature in Angular for transforming data in your templates. Whether you need to format dates, convert
strings to uppercase, or perform custom data transformations, Angular pipes provide a clean and declarative way to achieve
it. By leveraging built-in pipes and creating custom pipes, you can effectively format and manipulate data to meet the
requirements of your application's UI.

Q9. Explain about Angular dependency Injection?


A.)

Dependency Injection (DI) in Angular:


Dependency Injection is a design pattern where a class receives its dependencies from external sources rather than creating
them itself. In Angular, DI is used to provide components, services, and other objects with the dependencies they require.

How Dependency Injection Works in Angular:

WE Notes Unit - III,IV Complete (R-18) 34


1. Registration: Dependencies are registered with Angular's Dependency Injection system. This is typically done in the
providers array of an Angular module or directly within the metadata of a component or service.

2. Injection: When an object (such as a component or service) needs a dependency, Angular's DI system provides it by
injecting the dependency into the object's constructor or method.

Example:
Consider a simple service and a component in an Angular application:

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

@Injectable()
export class DataService {
getData(): string {
return 'Hello from DataService';
}
}

// Component
import { Component } from '@angular/core';
import { DataService } from './data.service';

@Component({
selector: 'app-my-component',
template: '<p>{{ message }}</p>',
providers: [DataService]
})
export class MyComponent {
message: string;

constructor(private dataService: DataService) {


this.message = this.dataService.getData();
}
}

In this example:

The DataService is a service that provides data.

The MyComponent component depends on the DataService to retrieve data.

Angular's DI system injects an instance of DataService into the MyComponent component's constructor.

The MyComponent component uses the injected DataService instance to retrieve data and display it.

Conclusion:
Dependency Injection is a fundamental concept in Angular that allows components, services, and other objects to receive
their dependencies from external sources. By using DI, Angular promotes modularity, testability, and reusability in your
application code. While there is no specific concept called "Angular dependency function," understanding how Dependency
Injection works is crucial for building Angular applications effectively.

WE Notes Unit - III,IV Complete (R-18) 35


Made with ❤️ by Telegram @0xrogerthat

WE Notes Unit - III,IV Complete (R-18) 36

You might also like