Full-stack development using MERN
Welcome to the world of MERN full stack development! In this book, we will delve into the intricacies of the MERN stack and learn how to build robust web applications using this powerful technology stack.
Throughout this book, we will cover the fundamental concepts of MERN development, including creating RESTful APIs with NodeJS and Express, designing dynamic user interfaces with React, and working with MongoDB to store and retrieve data.
In addition to learning these core concepts, we will also explore the applications of the MERN stack in various real-world scenarios, such as building e-commerce platforms, social media applications, and more.
Whether you are an experienced developer looking to expand your skillset or a newcomer to the world of web development, this book will provide you with the knowledge and tools needed to create robust, scalable, and performant web applications using the MERN stack.
Author: Tarun Singh Visit LinkedIn
Contributors:
- Sourabh Malewade Visit LinkedIn
- Swapnil Mistry Visit LinkedIn
Please note: Currently the notes are being update on this website, you will see more content in near future.
Who are we?
By adopting the pedagogy of learning by doing, we aim to bring innovation right into the educational structure at the edba academy. Beyond sharing lectures, books, and notes, our multi-skilled and industry-focused programs encourage students to apply their knowledge to real-life situations, personalizing the learning experience.
Our skill development courses are created to bridge the existing skill gap among the Indian youth while meeting the future skill requirements of various industries. With the whole community functioning as a learning ground, students are encouraged to develop a problem-solving mindset, widening their future career prospects and earning capacity.
How Internet Works?
-
When you type a web address into your browser (for our analogy that's like walking to the shop): The browser goes to the DNS server, and finds the real address of the server that the website lives on (you find the address of the shop).
-
The browser sends an HTTP request message to the server, asking it to send a copy of the website to the client (you go to the shop and order your goods). This message, and all other data sent between the client and the server, is sent across your internet connection using TCP/IP.
-
If the server approves the client's request, the server sends the client a "200 OK" message, which means "Of course you can look at that website! Here it is", and then starts sending the website's files to the browser as a series of small chunks called data packets (the shop gives you your goods, and you bring them back to your house).
-
The browser assembles the small chunks into a complete web page and displays it to you (the goods arrive at your door — new shiny stuff, awesome!).
References
Explore MDN Docs for further understanding of internet or world wide web
What is DNS?
DNS, or Domain Name System, is a hierarchical decentralized system that translates human-readable domain names into IP addresses. It acts as a directory service for the internet, helping users access websites and services using easy-to-remember domain names instead of numerical IP addresses. Working of DNS is as follows:
-
User Enters a Domain Name:
-
When a user enters a domain name (e.g., https://www.edba-academy.com/) into a web browser, the browser needs to find the IP address of the server hosting that website. Local DNS Resolver (DNS Resolver):
-
The user's device first checks its local DNS resolver, which is typically provided by the Internet Service Provider (ISP). This resolver may have the IP address for the requested domain in its cache. Root DNS Servers:
-
If the local resolver doesn't have the IP address, it contacts the root DNS servers. There are 13 root DNS servers worldwide. These servers provide information about top-level domains (TLDs) like .com, .org, and country-code TLDs (e.g., .uk, .jp). TLD DNS Servers:
-
The root DNS servers direct the resolver to the TLD DNS servers responsible for the specific domain extension (e.g., .com). The resolver then queries the TLD DNS servers for information about the authoritative name server for the requested domain. Authoritative Name Server:
-
The TLD DNS servers respond with the IP address of the authoritative name server for the requested domain. The authoritative name server holds the DNS records for the domain. Querying Authoritative Name Server:
-
The resolver sends a query to the authoritative name server, asking for the IP address associated with the requested domain. DNS Record Response:
-
The authoritative name server responds with the IP address for the requested domain. Cache Update:
-
The local resolver caches the IP address for future use, reducing the need to repeat the entire DNS lookup process for the same domain. Final IP Address Response:
-
The resolver provides the IP address to the user's device, allowing the browser to connect to the web server hosting the requested website.
Example:
-
Let's use the domain "https://www.edba-academy.com/" as an example:
-
User enters "https://www.edba-academy.com/" in the browser.
-
Local DNS resolver checks its cache.
-
If not found, it queries root DNS servers.
-
Root DNS servers direct to .com TLD DNS servers.
-
TLD DNS servers provide authoritative name server for "example.com."
-
Authoritative name server gives the IP address for "https://www.edba-academy.com/."
-
The IP address is returned to the local resolver.
-
The browser uses the IP address to connect to the web server hosting https://www.edba-academy.com/.
-
This entire process happens in the background, allowing users to access websites using easy-to-remember domain names while the underlying infrastructure deals with the translation to IP addresses.
Client Server Model
Client-Server Model in Website
- Definition: The client-server model is a fundamental architecture in web development, involving two main components: the client (user's device) and the server (remote computer hosting the website).
- Client (Frontend):
- Device (e.g., computer, smartphone) and web browser.
- Responsibilities: Rendering UI, handling user interactions.
- Technologies: HTML, CSS, JavaScript.
- Server (Backend):
- Remote computer hosting the website.
- Responsibilities: Handling requests, executing server-side logic, generating responses.
- Technologies: Server-side languages (e.g., Node.js), databases (e.g., MongoDB).
- Request-Response Cycle:
- User interacts with the website.
- Client sends requests to the server.
- Server processes requests, executes logic, and sends back responses.
- Client renders the received content.
- Communication Protocols:
- HTTP/HTTPS for client-server communication.
- WebSockets for real-time bidirectional communication.
- Security (HTTPS):
- Ensures secure data transmission using encryption.
- Utilizes SSL/TLS protocols.
Types of Client-Server Architecture: 1 Tier Model
Ref: https://www.prepbytes.com/blog/dbms/dbms-architecture/
- Definition: The 1-tier client-server model is the simplest architecture where both the client and server components reside on the same machine.
- Single Machine:
- Client-side and server-side components coexist on the user's device.
- Responsibilities:
- Client handles user interface and interactions.
- Server manages data processing and application logic.
- Use Cases:
- Typically used for small, standalone applications.
- Common in desktop applications where both UI and logic run locally.
- Advantages:
- Simplicity and ease of development.
- Minimal network communication overhead.
- Disadvantages:
- Limited scalability.
- May not suit distributed or large-scale applications.
- Example:
- A simple calculator application where the UI and calculation logic both run on the user's machine.
Types of Client-Server Architecture: 2 Tier Model
Ref: https://upload.wikimedia.org/wikipedia/commons/8/85/Client-Server_2-tier_architceture_-_en.png/
- Definition: The 2-tier client-server model involves two main components - the client, responsible for the user interface, and the server, handling data processing and storage.
- Client Tier:
- Responsible for the presentation layer and user interface.
- Interacts directly with the user.
- Executes application logic related to the user interface.
- Server Tier:
- Manages data processing and storage.
- Executes application logic related to data management.
- Typically hosts a database for persistent data storage.
- Communication:
- Communication between the client and server involves direct requests and responses.
- The client sends requests for data or operations, and the server responds accordingly.
- Use Cases:
- Commonly used for small to medium-sized applications.
- Suitable for scenarios where data processing and user interface can be logically separated.
- Advantages:
- Clear separation of concerns between user interface and data processing.
- Easier to maintain than a 1-tier model.
- Disadvantages:
- Limited scalability as both tiers are tightly coupled.
- Challenges with concurrent user access in certain scenarios.
- Example:
- A simple web application where the browser (client) interacts with a server hosting a database (server) to retrieve and store data.
In summary, the 2-tier client-server model introduces a separation between the user interface (client) and data processing (server), allowing for more organized development in comparison to the 1-tier model.
Types of Client-Server Architecture: 3 Tier Model
- Definition: The 3-tier client-server model involves three main components - the client (presentation), application server (logic), and database server (data).
- Client Tier (Presentation):
- Handles the user interface and user interactions.
- Displays information and captures user input.
- Executes presentation logic.
- Application Server Tier (Logic):
- Manages application logic and business rules.
- Processes user requests and performs necessary computations.
- Acts as an intermediary between the client and the database.
- Database Server Tier (Data):
- Stores and retrieves data.
- Manages data integrity and security.
- Executes database-related operations.
- Communication:
- Clients communicate with the application server for application logic.
- Application server communicates with the database server for data operations.
- Promotes a clear separation of concerns.
- Use Cases:
- Suitable for larger, more complex applications.
- Enhances scalability and maintainability.
- Allows for distributed development and specialization.
- Advantages:
- Improved organization and modularity.
- Easier maintenance and updates.
- Scalability due to separation of concerns.
- Disadvantages:
- Increased complexity compared to 2-tier models.
- Potential for increased network latency.
- Example:
- An e-commerce website where the browser (client) interacts with an application server for business logic, which in turn interacts with a database server for data retrieval and storage.
What is URL?
URL stands for Uniform Resource Locator. It is a reference or address used to access resources on the internet. A URL specifies the location of a resource, and the means by which to retrieve it. In simpler terms, a URL is what you type into the address bar of your web browser to go to a specific website or access a particular resource.
Anatomy of URL
Let's analyze the anatomy of the URL "https://www.edba-academy.com/" consists of several components, each serving a specific purpose. Here's the anatomy of the URL:
-
Scheme/Protocol:
- Component: https
- Purpose: Specifies the protocol or scheme used for communication. In this case, "https" indicates the use of the Hypertext Transfer Protocol Secure.
-
Subdomain:
- Component: www
- Purpose: Represents the subdomain of the website. It is optional and denotes a specific section or function of the site.
-
Domain:
- Component: edba-academy
- Purpose: Identifies the main domain or website. In this example, it is "edba-academy."
-
Top-Level Domain (TLD):
- Component: com
- Purpose: Specifies the top-level domain of the website. Common TLDs include ".com," ".org," ".net," etc.
-
Path:
- Component: /
- Purpose: Denotes the path or route on the server. In this case, "/" indicates the root directory.
-
Query Parameters:
- Component: (None in this example)
- Purpose: Additional parameters passed to the server, usually in the form of key-value pairs. They are preceded by a question mark "?" and separated by ampersands "&."
-
Fragment Identifier:
- Component: (None in this example)
- Purpose: Specifies a specific section or anchor within the document. It is preceded by a hash "#" symbol.
Putting it all together, the components of the URL "https://www.edba-academy.com/" can be described as follows:
- Scheme/Protocol: https
- Subdomain: www
- Domain: edba-academy
- Top-Level Domain (TLD): com
- Path: /
Understanding the anatomy of a URL is essential for web development and navigating the internet, as it helps in identifying the location and resources associated with a specific web address.
What is HTTP?
HTTP (Hypertext Transfer Protocol): HTTP, or Hypertext Transfer Protocol, is the foundation of any data exchange on the Web. It is an application layer protocol used for transmitting hypermedia documents, such as HTML. When you enter a URL into your web browser, the browser uses HTTP to communicate with the server and retrieve the web page you requested.
What is HTTPS?
HTTPS (Hypertext Transfer Protocol Secure): HTTPS is the secure version of HTTP. It uses encryption to secure the data transmitted between the user's browser and the website. This encryption is typically provided by Transport Layer Security (TLS) or its predecessor, Secure Sockets Layer (SSL). The use of HTTPS is essential for protecting sensitive information, such as login credentials and payment details, from eavesdroppers.
What are common HTTP Methods?
HTTP methods, also known as HTTP verbs, indicate the action to be performed on the resource identified by the URL. Here are some common HTTP methods:
-
GET:
- Purpose: Retrieve data from the server.
- Example: Requesting a webpage or an image.
-
POST:
- Purpose: Submit data to be processed to a specified resource.
- Example: Submitting a form with user input.
-
PUT:
- Purpose: Update a resource or create a new resource if it does not exist.
- Example: Updating a user's profile information.
-
DELETE:
- Purpose: Delete a specified resource.
- Example: Deleting a user account or a file.
-
PATCH:
- Purpose: Apply partial modifications to a resource.
- Example: Modifying specific fields of a resource without affecting the entire resource.
These HTTP methods provide a way for clients (such as browsers) to interact with servers in various ways, allowing for the retrieval, submission, modification, and deletion of resources.
Introduction to Web Development
The process of creating and maintaining websites or web applications, is web development.
-
Components:
- Frontend: The visual part users see and interact with (HTML, CSS, JavaScript).
- Backend: The behind-the-scenes processes, server logic, and database management.
-
Key Technologies:
- HTML: Defines the structure of web content.
- CSS: Styles and designs the visual presentation.
- JavaScript: Adds interactivity and dynamic features.
- Backend Languages: Server-side scripting (e.g., Node.js, Python, Ruby).
- Databases: Store and manage data (e.g., MongoDB, MySQL).
-
Applications:
- Websites: Informational or interactive pages accessible via a browser.
- Web Applications: Dynamic and interactive platforms with user-specific functionalities.
- E-commerce Sites: Online stores and payment systems.
-
Process:
- Design: Planning the structure, layout, and user experience.
- Development: Writing code for frontend and backend functionalities.
- Testing: Ensuring the website/application works as intended.
- Deployment: Making the site live and accessible on the internet.
- Maintenance: Regular updates, bug fixes, and improvements.
What is HTML?
HTML, or HyperText Markup Language, is the standard markup language used for creating web pages and web applications. It defines the structure and layout of a web document by using various tags and attributes to describe the content. HTML documents are interpreted by web browsers to render the content of a web page.
History of HTML:
-
Early Development: HTML was first introduced by Tim Berners-Lee while working at CERN in 1989. The initial version, HTML 1.0, was very basic and included only a few tags for structuring text documents.
-
Evolution: Over the years, HTML has gone through several iterations, with each new version introducing new features, elements, and improvements. HTML 2.0 was published in 1995, followed by HTML 3.2 in 1997, HTML 4.01 in 1999, and XHTML 1.0 in 2000.
-
HTML5: The latest major version of HTML is HTML5, which was finalized in 2014. HTML5 introduced many new elements and attributes, multimedia support (such as video and audio), enhanced forms, canvas for drawing graphics, and improved semantics for better accessibility and search engine optimization (SEO).
-
Living Standard: Unlike its predecessors, HTML5 is a "living standard" maintained by the World Wide Web Consortium (W3C) and the Web Hypertext Application Technology Working Group (WHATWG). This means that it continues to evolve and receive updates over time.
What is HTML Document (HTML Doc):
An HTML document, often referred to as an HTML file or web page, is a text file containing HTML markup that defines the structure and content of a web page. It typically consists of a combination of HTML elements, such as tags, attributes, and text content, arranged in a hierarchical structure. HTML documents can include text, images, links, multimedia, forms, and other types of content.
Here's a simple example of an HTML document:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sample HTML Document</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>This is a sample HTML document.</p>
</body>
</html>
In this example:
<!DOCTYPE html>
declares the document type and version of HTML being used.<html>
is the root element that wraps all other elements in the document.<head>
contains metadata and links to external resources.<meta>
specifies metadata such as character encoding and viewport settings.<title>
sets the title of the web page displayed in the browser's title bar or tab.<body>
contains the main content of the web page.<h1>
is a heading element.<p>
is a paragraph element.
HTML documents are the building blocks of the World Wide Web and are interpreted by web browsers to render web pages for users to interact with.
Skeleton or Structure of an HTML Webpage
- DOCTYPE Declaration:
The
<!DOCTYPE html>
declaration is used to specify the version of HTML being used. It should be placed at the very beginning of the HTML document to ensure that the browser renders the page in standards mode.
<!DOCTYPE html>
- HTML Root Element:
The
<html>
element serves as the root element of the HTML document and contains all other elements.
<html lang="en">
The lang attribute specifies the language of the document, which can help screen readers and search engines understand the content better. Replace "en" with the appropriate language code if necessary.
- Head Section:
The
<head>
section contains meta-information about the document, such as the document title, character encoding, viewport settings, and links to external resources like stylesheets and scripts.
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My HTML Website</title>
<!-- Additional meta tags, stylesheets, and scripts can be added here -->
</head>
The
<meta charset="UTF-8">
tag specifies the character encoding of the document as UTF-8, which supports a wide range of characters from different languages.
The
<meta name="viewport" content="width=device-width, initial-scale=1.0">
tag sets the viewport width to the width of the device and sets the initial zoom level to 1.0.
- Body Section:
The
<body>
section contains the main content of the HTML document, including text, images, links, forms, and other elements.
<body>
<!-- Header Section -->
<header>
<!-- Navigation Menu, Logo, etc. -->
</header>
<!-- Main Content Section -->
<main>
<!-- Content Goes Here -->
</main>
<!-- Footer Section -->
<footer>
<!-- Footer Content -->
</footer>
</body>
Header Section (
<header>
): Contains elements such as the navigation menu, logo, and other header-related content.
Main Content Section (
<main>
): Contains the primary content of the webpage, such as articles, sections, and other relevant content.
Footer Section (
<footer>
): Contains elements such as copyright information, contact details, and other footer-related content.
- Closing HTML Tag:
Finally, close the HTML document with the
</html>
tag.
</html>
By following this step-by-step structure, you can create a well-organized HTML skeleton for your website. Remember to fill in the content within each section according to your website's requirements.
What are tags in HTML?
In HTML, tags are used to define the structure and content of a web document. Tags are enclosed within angle brackets < > and typically come in pairs: an opening tag and a closing tag. The opening tag denotes the beginning of an element, and the closing tag denotes the end of that element. Tags can also be self-closing, meaning they don't have a separate closing tag.
There are different types of tags in HTML, including:
- Element Tags:
These are the most common type of tags used to define various elements in an HTML document. Examples include
<div>, <p>, <h1> to <h6>, <span>, <a>, <img>, <input>, <button>,
etc.
Example:
<div>This is a div element.</div>
<p>This is a paragraph element.</p>
<h1>This is a heading element.</h1>
<a href="https://www.example.com">This is a link element.</a>
<img src="image.jpg" alt="Description of image">
<input type="text" placeholder="Enter your name">
<button>Click me</button>
- Empty or Self-Closing Tags:
These tags do not have a separate closing tag and are self-contained. Examples include
<br>, <hr>, and <img>
.
Example:
<br> <!-- Line break -->
<hr> <!-- Horizontal rule -->
<img src="image.jpg" alt="Description of image">
- Comments:
Comments in HTML are used to add notes or annotations within the code that are not rendered in the browser. Comments start with
<!-- and end with -->
.
Example:
<!-- This is a comment -->
- Document Structure Tags:
These tags define the basic structure of an HTML document. Examples include
<html>, <head>, <title>, <body>, <meta>
, etc.
Example:
<!DOCTYPE html>
<html>
<head>
<title>Document Title</title>
</head>
<body>
<!-- Body content goes here -->
</body>
</html>
- Special Character Tags: These tags are used to display special characters in HTML, such as <, >, &, etc. Examples include <, >, &, etc.
Example:
<!-- This will display "<" -->
><!-- This will display ">" -->
&<!-- This will display "&" -->
These are some of the different types of tags in HTML, each serving a specific purpose in defining the structure and content of a web document.
What are elements in HTML?
In HTML, an element is a fundamental building block that defines the structure and content of a web document. Elements are made up of tags, which are enclosed within angle brackets < >. An HTML element typically consists of an opening tag, content, and a closing tag, although some elements may be self-closing.
There are different types of elements in HTML, including:
- Block-Level Elements:
Block-level elements are elements that typically start on a new line and take up the full width available. Examples include
<div>, <p>, <h1> to <h6>, <ul>, <ol>, <li>, <header>, <footer>, <section>, <article>
, etc.
Example:
<div>This is a block-level element.</div>
<p>This is a paragraph element.</p>
<h1>This is a heading element.</h1>
<ul>
<li>List item 1</li>
<li>List item 2</li>
</ul>
<header>This is a header element.</header>
<footer>This is a footer element.</footer>
- Inline Elements:
Inline elements are elements that do not start on a new line and only take up as much width as necessary. Examples include
<span>, <a>, <strong>, <em>, <img>, <input>, <button>, <br>, <a>
, etc.
Example:
<span>This is an inline element.</span>
<a href="#">This is an inline link element.</a>
<strong>This is bold text.</strong>
<em>This is italicized text.</em>
<img src="image.jpg" alt="Description of image">
<input type="text" placeholder="Enter your name">
<button>Click me</button>
- Document Structure Elements:
Document structure elements define the overall structure of an HTML document. Examples include
<html>, <head>, <title>, <body>, <meta>
, etc.
Example:
<!DOCTYPE html>
<html>
<head>
<title>Document Title</title>
</head>
<body>
<!-- Body content goes here -->
</body>
</html>
- Table Elements:
Table elements are used to create tables in HTML. Examples include
<table>, <tr>, <th>, <td>
, etc.
Example:
<table>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>Data 1</td>
<td>Data 2</td>
</tr>
</table>
- Form Elements:
Form elements are used to create forms in HTML for user input. Examples include
<form>, <input>, <textarea>, <select>, <button>
, etc.
Example:
<form>
<input type="text" placeholder="Enter your name">
<textarea placeholder="Enter your message"></textarea>
<select>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
<button>Submit</button>
</form>
These are some of the different types of elements in HTML, each serving a specific purpose in defining the structure and content of a web document.
How to write texts or what are tags with writeable content?
Texts: In HTML, text elements are used to display text content within a web page. This includes headings, paragraphs, lists, and inline text elements. Text elements are essential for conveying information and formatting content on a web page.
Examples of text elements:
- Headings:
<h1>, <h2>, <h3>, <h4>, <h5>, <h6>
- Paragraphs:
<p>
- Lists:
<ul>, <ol>, <li>
- Inline text:
<span>, <strong>, <em>, <a>, <br>, <hr>
- These elements are used to structure and format text content, making it easier to read and understand.
What is title tag in HTML?
Title:
The <title>
element is used to define the title of an HTML document. It is placed within the <head>
section of the document and is displayed in the title bar of the browser or in the tab of the webpage. The title of a webpage is important for search engine optimization (SEO) and helps users identify the content of the page.
Example:
<!DOCTYPE html>
<html>
<head>
<title>My Website Title</title>
</head>
<body>
<!-- Body content goes here -->
</body>
</html>
What is paragraph tag in HTML?
Paragraphs:
The <p>
element is used to define paragraphs of text within an HTML document. It represents a block of text with a line break before and after it. Paragraphs are commonly used to structure and organize textual content on a webpage.
Example:
<p>This is a paragraph element. It contains multiple lines of text and represents a block of content.</p>
Paragraphs are often used to present information in a structured and readable format, making it easier for users to consume the content.
What is body tag in HTML?
Body:
The <body>
element is used to define the main content of an HTML document. It contains all the content that is displayed in the browser window, including text, images, links, forms, and other elements. The <body>
element is a child of the <html>
element and is typically placed after the <head>
element.
Example:
<!DOCTYPE html>
<html>
<head>
<title>My Website Title</title>
</head>
<body>
<h1>Welcome to My Website</h1>
<p>This is the main content of the webpage.</p>
<!-- Other content goes here -->
</body>
</html>
The content within the <body>
element is what users see and interact with when they visit a webpage. It is where all the visible content of the webpage is contained.
What are list tags in HTML?
In HTML, a list is a type of element used to represent a collection of items in a structured format. Lists are commonly used to organize and present information in a structured and easy-to-read manner.
There are three main types of lists in HTML:
- Ordered List (
<ol>
):
An ordered list is a list of items where each item is preceded by a number or letter to indicate its order. Ordered lists are typically used when the order of items is important or meaningful.
Example:
<ol>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ol>
Output:
Item 1
Item 2
Item 3
- Unordered List (
<ul>
):
An unordered list is a list of items where each item is preceded by a bullet point or other marker to indicate its presence in the list. Unordered lists are typically used when the order of items is not important.
Example:
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
Output:
Item 1
Item 2
Item 3
- Definition List (
<dl>
):
A definition list is a list of terms and their corresponding definitions. Each term is represented using a <dt>
(definition term) element, and each definition is represented using a <dd>
(definition description) element.
Example:
<dl>
<dt>Term 1</dt>
<dd>Definition 1</dd>
<dt>Term 2</dt>
<dd>Definition 2</dd>
<dt>Term 3</dt>
<dd>Definition 3</dd>
</dl>
Output:
Term 1
: Definition 1
Term 2
: Definition 2
Term 3
: Definition 3
These are the three main types of lists in HTML, each serving a specific purpose in organizing and presenting information on a webpage.
What is semantic HTML?
Semantic HTML refers to the practice of using HTML elements to convey the meaning and structure of the content they contain. Semantic HTML aims to make the structure of a web page more meaningful and understandable to both browsers and developers. By using semantic HTML, developers can improve accessibility, search engine optimization (SEO), and maintainability of their web pages.
Semantic HTML elements are those that have a specific meaning and purpose, and they describe their content in a meaningful way. Examples of semantic HTML elements include <header>, <nav>, <main>, <section>, <article>, <aside>, <footer>, <h1> to <h6>, <p>, <ul>, <ol>, <li>, <blockquote>, <cite>, <figure>, <figcaption>
, etc.
Example of Semantic HTML:
<header>
<h1>Website Title</h1>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</header>
<main>
<section>
<h2>About Us</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</section>
<section>
<h2>Services</h2>
<ul>
<li>Service 1</li>
<li>Service 2</li>
<li>Service 3</li>
</ul>
</section>
</main>
<footer>
<p>© 2023 Company Name</p>
</footer>
What is non-semantic HTML?
Non-semantic HTML, on the other hand, refers to the use of generic or presentational HTML elements that do not convey any specific meaning or structure to the content they contain. Non-semantic HTML elements are often used purely for styling purposes and do not provide any meaningful information about the content.
Example of Non-semantic HTML:
<div class="header">
<h1>Website Title</h1>
<ul class="navigation">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</div>
<div class="main-content">
<div class="about">
<h2>About Us</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
<div class="services">
<h2>Services</h2>
<ul>
<li>Service 1</li>
<li>Service 2</li>
<li>Service 3</li>
</ul>
</div>
</div>
<div class="footer">
<p>© 2023 Company Name</p>
</div>
In the non-semantic example above, <div>
elements are used with class attributes to create layout structures, but they do not provide any information about the purpose or meaning of the content they contain. This makes it harder for both browsers and developers to understand the structure and meaning of the content.
Overall, using semantic HTML helps improve the accessibility, SEO, and maintainability of web pages by providing clear and meaningful structure to the content.
Elements classifications in HTML:
In HTML, elements are classified into two main categories: block-level elements and inline elements.
Block-Level Elements:
Block-level elements are elements that create a block of content and typically start on a new line, extending the full width available to them. They stack on top of each other vertically. Block-level elements are used to structure the layout of a webpage and typically contain other block-level or inline elements.
Examples of block-level elements include <div>, <p>, <h1> to <h6>, <ul>, <ol>, <li>, <header>, <footer>, <section>, <article>
, etc.
Example:
<div>This is a block-level element.</div>
<p>This is another block-level element.</p>
Inline Elements:
Inline elements are elements that do not start on a new line and only take up as much width as necessary. They flow within the content and allow other elements to sit beside them horizontally. Inline elements are typically used for styling or marking up small pieces of text within a block of content.
Examples of inline elements include <span>, <a>, <strong>, <em>, <img>, <input>, <button>, <br>, <a>
, etc.
Example:
<span>This is an inline element.</span>
<a href="#">This is another inline element (link).</a>
Divs and Spans:
<div>
and <span>
are generic container elements used for grouping and styling content in HTML.
<div>
(division) is a block-level element that is used to group together other block-level or inline elements. It is commonly used for creating layout structures and styling sections of a webpage.
Example:
<div>
<h1>This is a heading inside a div.</h1>
<p>This is a paragraph inside a div.</p>
</div>
<span>
is an inline element that is used to apply styles or markup to a specific piece of text within a block of content. It is commonly used for applying styles using CSS or for marking up small pieces of text.
Example:
<p>This is a <span style="color: blue;">blue</span> text.</p>
In summary, block-level elements create blocks of content that start on a new line and take up the full width available, while inline elements flow within the content and only take up as much width as necessary.
<div>
and<span>
are generic container elements used for grouping and styling content, with<div>
being block-level and<span>
being inline.
How to handle media in HTML?
In HTML, images, videos, and audios can be handled using specific elements and attributes to embed them into web pages. Here are examples of how to handle each of them:
Images:
Images can be displayed on a webpage using the <img>
element. The src attribute specifies the URL of the image, and the alt attribute provides alternative text for screen readers and in case the image cannot be displayed.
Example:
<img src="image.jpg" alt="Description of image">
Videos:
Videos can be embedded in a webpage using the <video>
element. The src attribute specifies the URL of the video file, and the <source>
element allows specifying multiple video formats for better browser compatibility. Additional attributes such as controls enable the default playback controls, and autoplay enables automatic playback.
Example:
<video width="320" height="240" controls autoplay>
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
Your browser does not support the video tag.
</video>
Audios:
Audio files can be included in a webpage using the <audio>
element. Similar to videos, the src attribute specifies the URL of the audio file, and the <source>
element allows specifying multiple audio formats. Additional attributes such as controls enable the default playback controls, and autoplay enables automatic playback.
Example:
<audio controls autoplay>
<source src="audio.mp3" type="audio/mpeg">
<source src="audio.ogg" type="audio/ogg">
Your browser does not support the audio tag.
</audio>
Responsive Images:
To ensure that images scale properly on different devices and screen sizes, you can use the srcset attribute along with the sizes attribute to specify different image sources and their corresponding sizes. This helps in serving the most appropriate image based on the device's pixel density and screen size.
Example:
<img srcset="image-320w.jpg 320w,
image-480w.jpg 480w,
image-800w.jpg 800w"
sizes="(max-width: 320px) 280px,
(max-width: 480px) 440px,
800px"
src="image-800w.jpg" alt="Description of image">
By using these HTML elements and attributes, you can effectively handle and display images, videos, and audios on your web pages.
Introduction to CSS
What is CSS?
CSS, or Cascading Style Sheets, is a style sheet language used to define the presentation and layout of HTML documents. CSS allows web developers to control the appearance of web pages, including elements such as colors, fonts, spacing, and layout. By separating the content (HTML) from the presentation (CSS), CSS enables consistent styling across multiple web pages and simplifies the process of updating and maintaining the visual design of a website.
History of CSS:
-
CSS1 (Cascading Style Sheets Level 1): CSS1 was the first version of CSS released in 1996. It introduced basic styling capabilities such as font properties, color, margins, padding, and background properties. CSS1 lacked support for many advanced features and layout techniques.
-
CSS2 (Cascading Style Sheets Level 2): CSS2 was released in 1998 and introduced more advanced styling features, including positioning, floating elements, and absolute and relative positioning. CSS2 also introduced support for media types and generated content.
-
CSS2.1: CSS2.1 is a revision of CSS2 that addresses inconsistencies and clarifies the specification. It was published as a W3C Recommendation in 2011 and serves as the foundation for modern CSS implementations.
These previous versions of CSS laid the groundwork for the development of modern CSS, which continues to evolve with new features and capabilities.
Types of CSS:
- Inline CSS: Inline CSS is applied directly within the HTML elements using the style attribute. This method is useful for applying specific styles to individual elements, but it can make the HTML code less readable and harder to maintain.
Example:
<p style="color: red;">This is a paragraph with inline CSS.</p>
- Internal CSS: Internal CSS is defined within the
<style>
element in the<head>
section of an HTML document. It applies styles to multiple elements within the same HTML file. While it keeps the styles separate from the HTML content, it still affects only the specific HTML document it is defined in.
Example:
<head>
<style>
p {
color: blue;
}
</style>
</head>
<body>
<p>This is a paragraph with internal CSS.</p>
</body>
- External CSS: External CSS is defined in a separate CSS file with a .css extension. This method allows for the separation of content and presentation, making it easier to maintain and update styles across multiple HTML files. The CSS file is linked to the HTML file using the
<link>
element in the<head>
section.
Example (styles.css):
p {
color: green;
}
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p>This is a paragraph with external CSS.</p>
</body>
CSS Fundamentals
- Selectors: Selectors are patterns used to select HTML elements that you want to style. They target specific elements based on their tag name, class, ID, attributes, or relationships with other elements. CSS selectors allow you to apply styles to specific elements or groups of elements.
Example:
/* Tag selector */
p {
color: blue;
}
/* Class selector */
.highlight {
background-color: yellow;
}
/* ID selector */
#header {
font-size: 24px;
}
- Properties: Properties are the characteristics or attributes of HTML elements that you can style using CSS. Properties define how elements look, such as their color, size, font, margin, padding, and more. Each property has a name and a value, which specify the desired style.
Example:
/* Property: Value */
color: blue;
font-size: 16px;
margin-top: 20px;
- Values: Values are the specific settings applied to CSS properties. Values can be keywords, numeric values, colors, lengths, percentages, or other valid CSS data types. Different properties accept different types of values, and the values you choose determine the appearance of the styled elements.
Example:
/* Keyword value */
font-family: Arial, sans-serif;
/* Numeric value */
font-size: 18px;
/* Color value */
color: #ff0000;
/* Length value */
margin-top: 10px;
/* Percentage value */
width: 50%;
- Selectors and Declarations: CSS rules consist of selectors and declarations. Selectors target HTML elements, and declarations define the styles to be applied to those elements. Declarations consist of properties and their corresponding values.
Example:
/* Selector */
p {
/* Declaration */
color: blue;
font-size: 16px;
}
- Cascading: Cascading refers to the process of combining multiple CSS rules to determine the final styles applied to an element. CSS rules can be defined in different stylesheets, inline styles, or in the same stylesheet with different levels of specificity. The browser applies the styles based on the specificity of the selectors and the order of precedence.
Example:
<style>
p {
color: blue; /* Applied */
}
p {
color: red; /* Overridden by the previous rule */
}
</style>
- Inheritance: Inheritance is the process by which certain CSS properties are passed from parent elements to their children. When a property is applied to a parent element, its value can be inherited by its child elements unless overridden by a more specific rule. Not all properties are inherited, and the inheritance behavior varies depending on the property.
Example:
/* Applied to the parent element */
.parent {
font-family: Arial, sans-serif;
}
/* Inherited by the child element */
.child {
/* Inherits font-family: Arial, sans-serif */
}
Backgrounds in CSS
In CSS, background colors and images are used to style the background of HTML elements. They allow you to set the color or display an image as the background of an element.
Let's explore background colors and images in CSS along with their attributes:
- Background Color: The background-color property is used to set the background color of an element. You can specify the color using a keyword, hexadecimal, RGB, RGBA, HSL, or HSLA value.
Example:
/* Using keyword */
body {
background-color: white;
}
/* Using hexadecimal value */
.container {
background-color: #f0f0f0;
}
/* Using RGBA value with transparency */
.overlay {
background-color: rgba(0, 0, 0, 0.5);
}
- Background Image: The background-image property is used to set an image as the background of an element. You can specify the URL of the image to be used.
Example:
/* Using a URL */
.banner {
background-image: url('banner.jpg');
}
- Background Image Properties:
When using background images, you can further customize their appearance and behavior using various CSS properties:
- background-repeat: Specifies how a background image should be repeated both horizontally and vertically. Possible values include repeat, repeat-x, repeat-y, and no-repeat.
- background-position: Specifies the starting position of a background image within its container. You can use keywords (top, center, bottom, left, right) or specify coordinates (x% y%, xpx ypx, x%, y%).
- background-size: Specifies the size of the background image. You can use keywords (auto, cover, contain) or specify dimensions (width height, auto height, width auto, percentage, cover, contain).
- background-attachment: Specifies whether the background image scrolls with the content or remains fixed. Possible values include scroll, fixed, and local.
Example:
.hero {
background-image: url('hero.jpg');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
background-attachment: fixed;
}
In this example, the background image is set to hero.jpg, it doesn't repeat (no-repeat), it's centered (background-position: center), it covers the entire container (background-size: cover), and it remains fixed as the content scrolls (background-attachment: fixed).
These are some of the basic properties and attributes used to style background colors and images in CSS. By using these properties, you can create visually appealing backgrounds for your web pages.
Margin And Padding
In CSS, margin and padding are two important properties used to add space around and within elements, respectively.
Above image is referenced from GeeksforGeeks
Margin refers to the space between an element and its neighboring elements, while padding refers to the space between an element and its content. Some examples of how to use these properties:
/* Set a margin of 10 pixels on all sides of a div element */
div {
margin: 10px;
}
/* Set different margin values for each side of an element */
div {
margin-top: 10px;
margin-right: 20px;
margin-bottom: 30px;
margin-left: 40px;
}
/* Set a padding of 20 pixels on all sides of a paragraph element */
p {
padding: 20px;
}
/* Set different padding values for each side of an element */
p {
padding-top: 10px;
padding-right: 20px;
padding-bottom: 30px;
padding-left: 40px;
}
In the first example, the margin property is used to add a margin of 10 pixels around all sides of a div element.
In the second example, the margin-* properties are used to set different margin values for each side of the div element.
In the third example, the padding property is used to add a padding of 20 pixels around all sides of a p element.
In the fourth example, the padding-* properties are used to set different padding values for each side of the p element.
Grid Layout
CSS grid layout is a powerful way to create two-dimensional layouts in CSS. It allows you to define rows and columns of grid cells, and then place content within those cells. Here are some ways to create grids in CSS:
Using the display: grid property: This is the most common way to create a grid layout in CSS. You can define the grid using the grid-template-rows and grid-template-columns properties, and then place content within the grid using the grid-row and grid-column properties.
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 200px;
}
.grid-item {
background-color: #ccc;
padding: 20px;
}
.item-1 {
grid-row: 1 / 3;
grid-column: 1 / 2;
}
.item-2 {
grid-row: 1 / 2;
grid-column: 2 / 4;
}
.item-3 {
grid-row: 2 / 3;
grid-column: 2 / 3;
}
In this example, we define a grid container with three columns and two rows. We then define three grid items and place them within the grid using the grid-row and grid-column properties.
Using the flexbox property: Flexbox is another way to create a grid layout in CSS. You can define a flex container with the display: flex property and then use the flex-basis property to define the width of each grid item.
.grid-container {
display: flex;
flex-wrap: wrap;
}
.grid-item {
flex-basis: 33.33%;
box-sizing: border-box;
padding: 10px;
}
In this example, we define a flex container with the display: flex property and wrap the items using the flex-wrap property. We then define each item with a flex-basis of 33.33%.
Overall, CSS grid layout is a powerful tool for creating complex layouts in CSS. You can use the display: grid property, the float property, or the flexbox property to create grids in CSS.
Responsive Web Design
Responsive web design is an approach to designing and developing websites that adapt to different screen sizes and devices. The main goal is to ensure that a website looks and functions well on all devices, from desktop computers to smartphones.
To write responsive CSS, there are several techniques available, including media queries, flexible grid systems, and fluid layouts.
Media Queries
different style for different media types
Media Queries deals with following:
- width and height of the viewport
- width and height of the device
- orientation
- resolution
What is viewport ?
The viewport is the area of a web page that's visible to the user. The viewport is a rectangle, the size of which is determined by the size of the user's device.
MQ Syntax
@media not|only mediatype and (expressions) {
CSS-Code;
}
Media queries are a key feature of responsive CSS. They allow you to target specific screen sizes or device types and apply different styles accordingly. For example, you can use a media query to apply different font sizes or adjust the layout of elements on a mobile device.
An example of how to use media queries in CSS to adjust the font size on different devices:
/* Default font size */
body {
font-size: 16px;
}
/* Media query for smaller screens */
@media only screen and (max-width: 768px) {
body {
font-size: 14px;
}
}
/* Media query for even smaller screens */
@media only screen and (max-width: 480px) {
body {
font-size: 12px;
}
}
Another way to write responsive CSS is to use a flexible grid system, such as Bootstrap or CSS Grid. These systems allow you to create a grid of columns that automatically adjust to different screen sizes. Here is an example using CSS Grid:
<div class="container">
<div class="row">
<div class="col">Column 1</div>
<div class="col">Column 2</div>
<div class="col">Column 3</div>
</div>
</div>
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
}
@media only screen and (max-width: 768px) {
.container {
grid-template-columns: repeat(2, 1fr);
}
}
@media only screen and (max-width: 480px) {
.container {
grid-template-columns: 1fr;
}
}
In this example, we create a container with a grid layout and three columns. We use the repeat function to create three columns that each take up one fraction of the available space (1fr). We also add a 20-pixel gap between the columns using the grid-gap property.
We then use media queries to adjust the number of columns as the screen size decreases. For example, on screens smaller than 768 pixels, we switch to a two-column layout, and on screens smaller than 480 pixels, we switch to a single column layout.
Overall, there are many ways to write responsive CSS, and the best approach will depend on the specific needs of your website. However, using media queries and flexible grid systems are two common and effective techniques for creating responsive designs.
Project: Simple responsive gallery
<html>
<head>
<title> Responsive Image Gallery</title>
<style>
body {
margin: 0;
padding: 0;
}
header {
text-align: center;
padding: 1rem auto;
}
.row {
display: flex;
flex-wrap: wrap;
}
.col {
flex: 25%;
}
img {
width: 100%;
margin-top: 10px;
}
@media screen and (max-width: 800px) {
.col {
flex: 50%;
}
}
@media screen and (max-width: 600px) {
.col {
flex: 100%;
}
}
</style>
</head>
<body>
<header>
<h1>A Responsive Image Gallery</h1>
</header>
<div class="row">
<div class="col">
<img
src="https://images.unsplash.com/photo-1676238540582-5958404206c2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8" />
<img
src="https://images.unsplash.com/photo-1676365743910-35ba5be051b8?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDE1fHhIeFlUTUhMZ09jfHxlbnwwfHx8fA%3D%3D" />
<img
src="https://images.unsplash.com/photo-1676271608840-9712fe255ae0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDE5fHhIeFlUTUhMZ09jfHxlbnwwfHx8fA%3D%3D" />
<img
src="https://images.unsplash.com/photo-1671483330944-36bbbe090e8a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8" />
</div>
<div class="col">
<img
src="https://images.unsplash.com/photo-1580664090511-35bbc93df9c1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDcxfHhIeFlUTUhMZ09jfHxlbnwwfHx8fA%3D%3D" />
<img
src="https://images.unsplash.com/photo-1676365743910-35ba5be051b8?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDE1fHhIeFlUTUhMZ09jfHxlbnwwfHx8fA%3D%3D" />
<img
src="https://images.unsplash.com/photo-1671483330944-36bbbe090e8a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8" />
<img
src="https://images.unsplash.com/photo-1676238540582-5958404206c2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8" />
</div>
<div class="col">
<img
src="https://images.unsplash.com/photo-1676271608840-9712fe255ae0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDE5fHhIeFlUTUhMZ09jfHxlbnwwfHx8fA%3D%3D" />
<img
src="https://images.unsplash.com/photo-1671483330885-62abe0be18a6?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDYyfHhIeFlUTUhMZ09jfHxlbnwwfHx8fA%3D%3D" />
<img
src="https://images.unsplash.com/photo-1671483330944-36bbbe090e8a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8" />
<img
src="https://images.unsplash.com/photo-1676238540582-5958404206c2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8" />
</div>
<div class="col">
<img
src="https://images.unsplash.com/photo-1676238540582-5958404206c2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8" />
<img
src="https://images.unsplash.com/photo-1671727337787-a08619e22c78?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDY0fHhIeFlUTUhMZ09jfHxlbnwwfHx8fA%3D%3D" />
<img
src="https://images.unsplash.com/photo-1676271608840-9712fe255ae0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDE5fHhIeFlUTUhMZ09jfHxlbnwwfHx8fA%3D%3D" />
<img
src="https://images.unsplash.com/photo-1671483330944-36bbbe090e8a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8" />
</div>
</div>
</body>
</html>
Create a basic webpage in HTML
In this project, we'll create a basic webpage for a fictional restaurant. We'll include elements such as headings, paragraphs, images, links, lists, forms, and more.
Here's a step-by-step guide to creating the HTML project:
-
Create a New HTML File: Create a new file with a .html extension, such as index.html, using a text editor or an HTML editor like Visual Studio Code, Sublime Text, or Notepad++.
-
HTML Structure: Start by defining the basic structure of the HTML document using the
<!DOCTYPE html>
declaration and the<html>, <head>, and <body>
elements.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Restaurant Website</title>
</head>
<body>
</body>
</html>
- Header Section: Add a header section containing the restaurant's name and a navigation menu.
<header>
<h1>My Restaurant</h1>
<nav>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#menu">Menu</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</header>
- Main Content Section: Add a main content section with information about the restaurant, including an image, a paragraph, and a list of menu items.
<main>
<section id="home">
<h2>Welcome to Our Restaurant</h2>
<img src="restaurant.jpg" alt="Restaurant Image">
<p>We serve delicious dishes made with fresh ingredients.</p>
</section>
<section id="menu">
<h2>Menu</h2>
<ul>
<li>Appetizers</li>
<li>Main Courses</li>
<li>Desserts</li>
</ul>
</section>
</main>
- Footer Section: Add a footer section with contact information and social media links.
<footer id="contact">
<p>Contact Us:</p>
<p>123 Restaurant Street, City</p>
<p>Email: info@example.com</p>
<p>Phone: 123-456-7890</p>
<nav>
<ul>
<li><a href="#">Facebook</a></li>
<li><a href="#">Twitter</a></li>
<li><a href="#">Instagram</a></li>
</ul>
</nav>
</footer>
- Closing Tags: Close the remaining tags to ensure proper structure.
</body>
</html>
- Add CSS (Optional): Optionally, you can add CSS styles to enhance the appearance of your webpage. You can either use inline styles within the HTML document or link an external CSS file.
Example of inline styles:
<header style="background-color: #333; color: #fff; padding: 10px;">
That's it! You've created a basic HTML project for a restaurant website.
Add CSS to above web page:
-
Create a CSS File: First, create a new file named styles.css in the same directory as your HTML file.
-
Link CSS File to HTML: In the
<head>
section of your HTML file, add a link to the CSS file using the<link>
element. This allows the browser to apply the styles defined in the CSS file to the HTML content.
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Restaurant Website</title>
<link rel="stylesheet" href="styles.css">
</head>
- Define Global Styles:
Start by defining global styles that apply to the entire webpage. In this case, we'll set the font family, margin, padding, and background color for the
<body>
element.
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
These styles ensure a consistent look and feel across the entire webpage by setting the default font family, removing any default margin and padding, and setting a background color.
- Define Header Styles:
Next, define styles for the header section of the webpage. We'll set the background color, text color, padding, and text alignment for the
<header>
element. We'll also style the heading (<h1>
) and the navigation links (<nav> and <ul>
).
header {
background-color: #333;
color: #fff;
padding: 10px;
text-align: center;
}
header h1 {
margin: 0;
}
nav ul {
list-style-type: none;
margin: 0;
padding: 0;
}
nav ul li {
display: inline;
margin-right: 20px;
}
nav ul li a {
color: #fff;
text-decoration: none;
}
These styles define the appearance of the header section, including its background color, text color, padding, and text alignment. They also style the heading and navigation links for better readability and visual appeal.
- Define Main Content Styles:
Define styles for the main content section of the webpage. We'll set padding for the
<main>
element and margin-bottom for<section>
elements.
main {
padding: 20px;
}
section {
margin-bottom: 20px;
}
These styles add spacing and separation between different sections of the main content, improving readability and visual hierarchy.
- Define Footer Styles:
Finally, define styles for the footer section of the webpage. We'll set the background color, text color, padding, and text alignment for the
<footer>
element. We'll also style the paragraph (<p>
) and navigation links (<nav> and <ul>
).
footer {
background-color: #333;
color: #fff;
padding: 20px;
text-align: center;
}
footer p {
margin: 5px 0;
}
footer nav ul li {
display: inline;
margin-right: 10px;
}
footer nav ul li a {
color: #fff;
text-decoration: none;
}
These styles define the appearance of the footer section, including its background color, text color, padding, and text alignment. They also style the paragraphs and navigation links for better visual appeal and accessibility
That's it! You've successfully added CSS styles to the HTML project for the restaurant website, enhancing its appearance and layout. Each CSS rule serves a specific purpose in defining the visual presentation of different elements on the webpage.
JavaScript Basics
JavaScript is a high-level, dynamic, and interpreted programming language that is primarily used for creating interactive client-side web applications, but it can also be used on the server-side through NodeJS. It was created in 1995 by Brendan Eich, who was then working at Netscape Communications Corporation.
Core features of JavaScript
-
Object-Oriented Programming (OOP): JavaScript is an object-oriented programming language, which means that it supports the creation of objects with their own properties and methods. Objects are a fundamental concept in JavaScript and are used extensively in the language.
-
Dynamic Typing: JavaScript is dynamically typed, which means that the data type of a variable can change at runtime. This makes JavaScript very flexible and easy to use.
-
First-Class Functions: JavaScript functions are first-class citizens, which means that they can be passed around like any other data type. Functions can also be used as arguments to other functions, and they can be returned as values from functions.
-
Asynchronous Programming: JavaScript has built-in support for asynchronous programming, which means that it can execute multiple operations simultaneously without blocking the execution of other code. This is typically used in web applications to make requests to servers without blocking the UI.
-
Prototypal Inheritance: JavaScript uses prototypal inheritance, which is a different approach to inheritance than classical inheritance used in languages like Java and C++. This allows for more flexible object creation and is a key feature of the language.
JS Fundamentals
Data types in JavaScript
Primitive data types
-
String: used to represent textual data, such as names or messages. Strings are enclosed in single or double quotes.
-
Number: used to represent numerical data, including integers and floating-point numbers.
-
Boolean: used to represent true/false values.
-
Undefined: used to represent the absence of a value. A variable that has not been assigned a value is undefined.
-
Null: used to represent the intentional absence of any object value.
-
Symbol: a new data type added in ES6, which represents a unique identifier. Symbols are often used as keys in objects.
JavaScript also has one non-primitive data type
- Object: used to represent complex data structures, such as arrays, functions, and objects. Objects are a key feature of JavaScript, and many of the language's features are built around them.
Example of how variables are declared, initialized and accessed in JavaScript:
// Declare a variable called 'name'
let name;
// Initialize the variable 'name' with the value 'John'
name = 'John';
// Declare and initialize a variable called 'age' with the value 30
let age = 30;
// Print the values of 'name' and 'age' to the console
console.log(name);
console.log(age);
Let's break down each line and see what it does:
-
let name; declares a variable called 'name' without initializing it. This is known as a variable declaration.
-
name = 'John'; assigns the value 'John' to the variable 'name'. This is known as variable initialization.
-
let age = 30; declares and initializes a variable called 'age' with the value 30.
-
console.log(name); prints the value of 'name' to the console. The console is a tool used in web development that displays messages and logs in real-time, and is accessible through the developer console of most modern web browsers.
-
console.log(age); prints the value of 'age' to the console.
When you run this code in a JavaScript environment, such as a web browser console or a NodeJS environment, you will see the values of 'name' and 'age' printed to the console:
John
30
In this example, we used the let keyword to declare variables, which is the recommended way to declare variables in modern JavaScript. The let keyword allows us to declare variables that can be reassigned to a new value later on in the program.
Variable Declaration and Initialization in JS
In JavaScript, variables are stored in memory as part of the execution context. When a variable is declared, space is reserved in memory to store its value.
When a variable is accessed in JavaScript, the engine looks up the variable in memory and retrieves its value. This process is known as variable resolution.
Here's what happens behind the scenes of JavaScript when a variable is declared and defined:
-
Declaration: When a variable is declared using the let, const, or var keyword, the JavaScript engine creates a new identifier in memory with the name of the variable. The identifier is assigned a reference to a memory location where the value of the variable will be stored.
-
Initialization: When a variable is initialized, the engine assigns a value to the memory location that was reserved for the variable. If the variable is not initialized at the time of declaration, its value is set to undefined.
-
Assignment: When a value is assigned to a variable using the = operator, the value is stored in the memory location reserved for the variable.
-
Scope: Variables in JavaScript are scoped to the function or block in which they are declared. This means that variables declared inside a function are not accessible outside of the function.
-
Garbage Collection: When a variable is no longer needed, JavaScript automatically removes it from memory through a process called garbage collection. This frees up memory that can be used by other parts of the program.
It's important to note that variables in JavaScript are dynamically typed, which means that their data type can change during the execution of the program. This is in contrast to statically typed languages, where the data type of a variable is fixed at compile time.
Data type: String
In JavaScript, a string is a sequence of characters enclosed in single or double quotes. Strings are one of the most common data types in JavaScript and are used to represent text.
Common string manipulation in JS are:
- Concatenation: You can concatenate two or more strings using the + operator. For example, if you have two strings "hello" and "world", you can concatenate them like this:
let greeting = "hello";
let name = "world";
let message = greeting + " " + name;
console.log(message); // Output: "hello world"
- String Length: You can find the length of a string using the length property. For example:
let myString = "This is a string";
console.log(myString.length); // Output: 16
- Accessing Characters: You can access individual characters in a string using square brackets and the index of the character you want. For example: javascript
let myString = "hello";
console.log(myString[0]); // Output: "h"
console.log(myString[3]); // Output: "l"
- Substring: You can extract a portion of a string using the substring method. For example:
let myString = "hello world";
let subString = myString.substring(0, 5); // Extracts the first 5 characters
console.log(subString); // Output: "hello"
- Replace: You can replace one or more occurrences of a substring in a string using the replace method. For example:
let myString = "hello world";
let newString = myString.replace("world", "javascript");
console.log(newString); // Output: "hello javascript"
Important features of string in JS are:
-
Strings are immutable: This means that once you create a string, you cannot change the individual characters in it. Instead, you must create a new string with the desired changes.
-
Strings are iterable: This means that you can loop over the characters in a string using a for loop or other iterable methods like forEach or map.
-
Strings have many built-in methods: JavaScript provides many methods for working with strings, such as substring, replace, and split. These methods make it easy to manipulate strings in various ways.
-
Strings can be converted to other data types: You can convert a string to a number using the parseInt or parseFloat methods. You can also convert a string to an array using the split method.
Overall, strings are an essential data type in JavaScript and are used extensively in web development. Understanding how to manipulate strings is crucial for building effective JavaScript applications.
Data type: Undefined and Null
In JavaScript, both undefined and null are special values that represent the absence of a value or an empty value. However, they are not interchangeable, and they have slightly different meanings.
Undefined
undefined is a primitive value that represents a variable that has been declared but has not been assigned a value. It also represents a function that has been defined but has no return statement.
Here's an example of a variable that is declared but not assigned a value:
let foo;
console.log(foo); // Output: undefined
In this example, the variable foo is declared but not assigned a value. When we try to log the value of foo to the console, we get undefined.
Here's an example of a function that does not have a return statement:
function bar() {}
console.log(bar()); // Output: undefined
In this example, the function bar is defined but does not have a return statement. When we call the function and try to log the return value to the console, we get undefined.
Null
null is also a primitive value that represents the intentional absence of any object value. It is often used to indicate that a variable or object property has no value.
Here's an example of a variable that is explicitly set to null:
let bar = null;
console.log(bar); // Output: null
In this example, the variable bar is explicitly set to null. When we log the value of bar to the console, we get null.
Here's an example of an object property that is set to null:
const person = {
name: 'John',
age: null,
};
console.log(person.age); // Output: null
In this example, the age property of the person object is set to null. When we log the value of person.age to the console, we get null.
Difference between Undefined and Null
The main difference between undefined and null is that undefined is the default value of a variable that has not been assigned a value, whereas null is an intentional absence of any object value. undefined is also a primitive value, whereas null is an object value. In general, you should use undefined to represent the absence of a value that should have been assigned, and use null to represent the intentional absence of any object value (empty).
Data type: Number
The Number data type in JavaScript is used to represent numeric values, both integers and floating-point numbers.
Some examples of numbers declaration in JavaScript:
let integer = 42; // integer number
let floatingPoint = 3.14; // floating-point number
let negativeNumber = -10; // negative number
let scientificNotation = 2.998e8; // scientific notation
The core features of the Number data type in JavaScript include the ability to perform arithmetic operations such as addition, subtraction, multiplication, and division. It also supports several mathematical methods such as Math.sqrt() (to find the square root), Math.pow() (to raise a number to a power), and Math.abs() (to find the absolute value of a number).
Examples of number-related manipulations in JavaScript:
let x = 10;
let y = 5;
// Addition
let sum = x + y; // 15
// Subtraction
let difference = x - y; // 5
// Multiplication
let product = x * y; // 50
// Division
let quotient = x / y; // 2
// Remainder (modulo)
let remainder = x % y; // 0
// Exponentiation
let exponentiation = x ** y; // 100000
// Square root
let squareRoot = Math.sqrt(x); // 3.1622776601683795
// Absolute value
let absoluteValue = Math.abs(-10); // 10
Additionally, JavaScript provides several methods for converting strings to numbers and vice versa. For example, the parseInt() method can be used to convert a string to an integer, and the parseFloat() method can be used to convert a string to a floating-point number.
let stringNumber = "42";
let parsedInteger = parseInt(stringNumber); // 42
let stringFloat = "3.14";
let parsedFloat = parseFloat(stringFloat); // 3.14
It is worth noting that JavaScript's Number data type has some limitations due to the way it represents numbers internally. Specifically, it can only represent numbers up to a certain precision (approximately 15-17 decimal digits), and certain arithmetic operations can lead to rounding errors. Therefore, it is important to be aware of these limitations when working with large numbers or performing precise calculations.
Data type: Boolean
Boolean data type is used to represent logical values - true or false. It is a primitive data type, meaning that it is not an object and does not have any methods or properties.
Examples of Boolean values in JavaScript:
let isTrue = true;
let isFalse = false;
In addition to these literal values, Boolean values can also be the result of logical expressions. For example:
let x = 10;
let y = 5;
let greaterThan = x > y; // true
let lessThan = x < y; // false
let isEqual = x === y; // false
let notEqual = x !== y; // true
Here, the expressions x > y, x < y, x === y, and x !== y all evaluate to Boolean values - either true or false - based on the comparison being made.
Boolean values are often used in conditional statements to control the flow of a program. For example:
let age = 18;
if (age >= 18) {
console.log("You are old enough to vote.");
} else {
console.log("You are not old enough to vote.");
}
Objects in JS
An object is a data type that represents a collection of related data and/or functionality. Objects are used to organize and store data in a structured way.
Important features of objects in JavaScript:
- Properties: Objects have properties, which are key-value pairs. The key is a string (or symbol), and the value can be any data type, including other objects. Properties are accessed using dot notation or bracket notation. Example:
let person = {
name: "John",
age: 30,
address: {
street: "123 Main St",
city: "Anytown",
state: "CA"
}
};
console.log(person.name); // "John"
console.log(person.address.city); // "Anytown"
- Methods: Objects can have methods, which are functions that are properties of the object. Methods are accessed using dot notation. Example:
let person = {
name: "John",
age: 30,
sayHello: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
person.sayHello(); // "Hello, my name is John"
- Constructors: Objects can be created using constructor functions, which are functions that are used to create new objects. Constructor functions use the new keyword to create a new instance of the object. Example:
function Person(name, age) {
this.name = name;
this.age = age;
this.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
}
let person1 = new Person("John", 30);
let person2 = new Person("Jane", 25);
console.log(person1.name); // "John"
console.log(person2.age); // 25
person1.sayHello(); // "Hello, my name is John"
- Prototypes: Objects can inherit properties and methods from a prototype object, which is a template object that is used to create new objects. Prototypes are accessed using the prototype property of a constructor function. Example:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
let person1 = new Person("John", 30);
let person2 = new Person("Jane", 25);
console.log(person1.name); // "John"
console.log(person2.age); // 25
person1.sayHello(); // "Hello, my name is John"
Some common manipulations related to objects in JavaScript include:
- Adding and deleting properties:
let person = {
name: "John",
age: 30
};
person.address = "123 Main St";
delete person.age;
console.log(person); // { name: "John", address: "123 Main St" }
- Looping over properties:
let person = {
name: "John",
age: 30
};
for (let prop in person) {
console.log(`${prop}: ${person[prop]}`);
}
// Output:
// name: John
// age: 30
- Cloning objects:
let person = {
name: "John",
age: 30
};
let clone = Object.assign({}, person);
console.log(clone); // { name: "John", age: 30 }
Loop / Iterate through JS Objects
There are different ways to loop through JS objects.
- for...in loop: This loop is used to iterate over the properties of an object. Example:
let person = {
name: "John",
age: 30,
gender: "male"
};
for (let prop in person) {
console.log(`${prop}: ${person[prop]}`);
}
// Output:
// name: John
// age: 30
// gender: male
- Object.keys() method: This method returns an array of the object's own enumerable properties (keys), which can be looped through using a for...of loop or forEach() method. Example:
let person = {
name: "John",
age: 30,
gender: "male"
};
let keys = Object.keys(person);
for (let key of keys) {
console.log(`${key}: ${person[key]}`);
}
// Output:
// name: John
// age: 30
// gender: male
- Object.values() method: This method returns an array of the object's own enumerable property values, which can be looped through using a for...of loop or forEach() method. Example:
let person = {
name: "John",
age: 30,
gender: "male"
};
let values = Object.values(person);
for (let value of values) {
console.log(value);
}
// Output:
// John
// 30
// male
- Object.entries() method: This method returns an array of the object's own enumerable property key-value pairs as arrays, which can be looped through using a for...of loop or forEach() method. Example:
let person = {
name: "John",
age: 30,
gender: "male"
};
let entries = Object.entries(person);
for (let [key, value] of entries) {
console.log(`${key}: ${value}`);
}
// Output:
// name: John
// age: 30
// gender: male
Arrays in JS
An array is a collection of elements of any data type that are stored in contiguous memory locations. Arrays are commonly used to store and organize related data.
Arrays in JavaScript are stored as objects in memory, with each element being a property of the array object. The index of each element is used as the property name.
Example of creating an array in JavaScript:
let myArray = [1, 2, 3, 4, 5];
In the example above, we have created an array called myArray that contains five elements of type number.
To access elements of an array in JavaScript, we use square brackets with the index of the element we want to access. The first element of an array has an index of 0, the second element has an index of 1, and so on.
- Example of accessing elements of an array in JavaScript:
let myArray = [1, 2, 3, 4, 5];
console.log(myArray[0]); // Output: 1In the example above, we are accessing the first and third elements of the myArray array using their index.
- We can also change the value of an array element by assigning a new value to it using its index: console.log(myArray[2]); // Output: 3
let myArray = [1, 2, 3, 4, 5];
myArray[0] = 6;
console.log(myArray); // Output: [6, 2, 3, 4, 5]
In the example above, we are changing the value of the first element of the myArray array from 1 to 6.
- We can also add elements to an array using the push() method, remove elements using the pop() method, or insert elements using the splice() method.
Examples of using these methods:
let myArray = [1, 2, 3, 4, 5];
myArray.push(6);
console.log(myArray); // Output: [1, 2, 3, 4, 5, 6]
myArray.pop();
console.log(myArray); // Output: [1, 2, 3, 4, 5]
myArray.splice(2, 0, 7);
console.log(myArray); // Output: [1, 2, 7, 3, 4, 5]
In the examples above, we are adding an element to the end of the myArray array using push(), removing the last element of the array using pop(), and inserting an element at index 2 using splice().
JavaScript Execution
JavaScript is an interpreted language, which means that it executes code directly, without needing to compile it beforehand. When a program or script is executed in JavaScript, there are several steps involved in the process.
V8 Engine
JavaScript Engine
The JavaScript engine is just one of the many components that make up a modern web browser. The browser engine is the main component responsible for rendering web pages, and it consists of several different modules that work together to process HTML, CSS, and JavaScript code.
Components of JavaScript Engine
-
Parser: The parser component of the engine is responsible for converting JavaScript source code into an Abstract Syntax Tree (AST). This is the first step in the execution process, and it enables the engine to analyze and optimize the code.
-
Interpreter: The interpreter component of the engine reads the AST generated by the parser and executes the code. It does this by converting the AST into machine code, which can be executed by the computer's CPU.
-
Compiler: The compiler component of the engine is responsible for optimizing the code by analyzing its structure and behavior. The engine uses a technique called "Just-in-time" (JIT) compilation to improve the performance of JavaScript code. This involves analyzing the code at runtime and generating optimized machine code that can be executed more quickly.
-
Garbage Collector: The garbage collector component of the engine is responsible for managing memory usage in the JavaScript program. It monitors the objects created by the program and frees up memory that is no longer in use.
-
Profiler: The profiler component of the engine is used to monitor the performance of JavaScript code. It provides detailed information about the execution time of different parts of the code, allowing developers to identify and optimize performance bottlenecks.
Chrome V8 Engine
JavaScript Chrome V8 engine is an open-source JavaScript engine developed by Google that powers the Google Chrome web browser and other web applications. It is written in C++ and is designed to be fast, efficient, and scalable. The V8 engine is made up of several components, each of which plays a specific role in the JavaScript execution process.
Components of Chrome V8 Engine
-
NodeJs Core or JavaScript Core: This contains core of JS functionalities and utilities.
-
NodeJs Bindings: This helps to process functions from JS or NodeJS to C++.
-
Google V8 (C++): This is the core of JS engine which helps to the run the code exactly.
-
libuv: This is the pool of utilities or also worker threads which helps to run additional functionality or asynchronous tasks.
Note: when talking only about JS (not NodeJS) the libuv does not exist in the engine and it is replaced by Browser Web APIs.
JavaScript Event Loop
The event loop in JS is a single main thread which is responsible for the execution of the code.
Major components of JS event loop
- Main Thread (Event Loop) : responsible for execution of the flow
- Call Stack : the stack which hold the lastest part of the code which needs to be executed
- Callback Queues : holds the response generated from Web APIs once the task/function is completed
- Web APIs : runs the additional functionality required and handles the asynchronous aspect of the execution
Callbacks
What is callbacks ?
- Callbacks are function which are passed as arguments in other functions and these callback is trigger when the task/request is completed.
- A triggered callback will contain, error if any, data and other options if specified.
- This callback returns the data to main process.
Drawback of Callbacks
Callback Hell
getData(function(a) {
getMoreData(a, function(b) {
getMoreData(b, function(c) {
getMoreData(c, function(d) {
getMoreData(d, function(e) {
// ...
})
})
})
})
})
- Even though callbacks provide flexibility to handle async situation but it is a hard concept to understand.
- Using callbacks can lead code unreadability, it becomes difficult to keep track on things.
Asynchronous Programming
- In sync operations, the process completes the task then it hands over back the main control, till then no other task can be performed.
- In async operations, the process is handed over to worker threads and they completes the task and returns the output to the process back.
- In this while the main process is free and hence it can perform other tasks.
Promises
Asynchronous programming can be handled with promises instead of creating a lot of callbacks in functions.
When there is a lengthy chain of callback functions used to implement numerous asynchronous tasks, it becomes difficult to maintain the application. We can utilise promise to address this issue. It is a neat technique to use JavaScript to do asynchronous programming.
A Promise in JavaScript is an object representing the eventual completion or failure of an asynchronous operation and its resulting value. Promises provide a cleaner and more organized way to write asynchronous code than using callbacks. They also allow for more advanced flow control and error handling.
Here's an example of how to use Promises in JavaScript:
function fetchUserData(userId) {
return new Promise((resolve, reject) => {
const url = `https://api.example.com/users/${userId}`;
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function() {
if (xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
resolve(data);
} else {
reject(new Error('Failed to fetch user data'));
}
};
xhr.onerror = function() {
reject(new Error('Network error'));
};
xhr.send();
});
}
fetchUserData(123)
.then((data) => {
console.log('User data:', data);
})
.catch((error) => {
console.error('Error:', error);
});
In this example, we define a function fetchUserData that returns a Promise. Inside the Promise, we make an AJAX request to fetch user data from a server. If the request is successful, we call the resolve method and pass the resulting data as an argument. If the request fails, we call the reject method and pass an error object as an argument.
We then call the fetchUserData function with a user ID of 123, and use the then method to handle the resolved Promise with a callback function that logs the user data in then block and error in catch block.
Exercise: Array
Practice Exercises: JavaScript
Note: These questions are meant to guide you through different topics and methods to solve. It is expected that you should explore these topics on your own and practice more as much as possible.
What will be the output of the following code?
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let arr3 = arr1.concat(arr2);
console.log(arr3);
Answer: [1, 2, 3, 4, 5, 6]
Explanation: concat() method concatenates two or more arrays and returns a new array containing the elements from all the arrays. In this case, it will return a new array [1, 2, 3, 4, 5, 6].
What will be the output of the following code?
let arr = [1, 2, 3, 4, 5];
let slicedArr = arr.slice(1, 3);
console.log(slicedArr);
Answer: [2, 3]
Explanation: slice() method returns a new array containing the elements from the start index to the end index. In this case, it will return a new array [2, 3].
What will be the output of the following code?
let arr = [1, 2, 3];
arr.push(4);
console.log(arr);
Answer: [1, 2, 3, 4]
Explanation: push() method adds one or more elements to the end of an array and returns the new length of the array. In this case, it will add the element 4 to the end of the array and return a new array [1, 2, 3, 4].
What will be the output of the following code?
let arr = [1, 2, 3];
let poppedElement = arr.pop();
console.log(poppedElement);
Answer: 3
Explanation: pop() method removes the last element from an array and returns that element. In this case, it will remove the last element 3 from the array and return it.
What will be the output of the following code?
let arr = [1, 2, 3];
let reversedArr = arr.reverse();
console.log(reversedArr);
Answer: [3, 2, 1]
Explanation: reverse() method reverses the order of the elements in an array and returns the reversed array. In this case, it will return a new array [3, 2, 1].
Write a function that takes an array of numbers and returns a new array containing only the even numbers.
function getEvenNumbers(arr) {
let evenArr = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] % 2 === 0) {
evenArr.push(arr[i]);
}
}
return evenArr;
}
// Example usage:
let numbers = [1, 2, 3, 4, 5, 6, 7, 8];
let evenNumbers = getEvenNumbers(numbers);
console.log(evenNumbers); // Output: [2, 4, 6, 8]
Write a function that takes an array of strings and returns a new array containing only the strings that have a length greater than 5.
function getLongStrings(arr) {
let longStrings = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i].length > 5) {
longStrings.push(arr[i]);
}
}
return longStrings;
}
// Example usage:
let strings = ['apple', 'banana', 'pear', 'pineapple', 'grapefruit'];
let longStrings = getLongStrings(strings);
console.log(longStrings); // Output: ['pineapple', 'grapefruit']
How can you filter an array of objects based on a certain condition using Array.filter() method in JavaScript?
const persons = [
{ name: 'John', age: 24 },
{ name: 'Jane', age: 30 },
{ name: 'Mary', age: 19 },
{ name: 'Peter', age: 40 }
];
const filteredPersons = persons.filter(person => person.age >= 30);
console.log(filteredPersons); // [{ name: 'Jane', age: 30 }, { name: 'Peter', age: 40 }]
In this example, the Array.filter() method is used to filter an array of objects based on a condition. In this case, we want to filter the persons array to include only those objects where the age property is greater than or equal to 30. The Array.filter() method takes a callback function as an argument which returns a boolean value based on the condition. If the callback function returns true, the object is included in the filtered array, otherwise it is excluded.
How can you use the Array.map() method in JavaScript to transform an array of objects to another format?
const persons = [
{ name: 'John', age: 24 },
{ name: 'Jane', age: 30 },
{ name: 'Mary', age: 19 },
{ name: 'Peter', age: 40 }
];
const formattedPersons = persons.map(person => {
return {
firstName: person.name,
age: person.age
};
});
console.log(formattedPersons);
// [{ firstName: 'John', age: 24 }, { firstName: 'Jane', age: 30 }, { firstName: 'Mary', age: 19 }, { firstName: 'Peter', age: 40 }]
In this example, the Array.map() method is used to transform an array of objects to another format. In this case, we want to create a new array of objects where the name property is renamed to firstName. The Array.map() method takes a callback function as an argument which returns the transformed object. The returned value is used to create a new array.
How can you use the Array.reduce() method in JavaScript to calculate the sum of an array of numbers?
const numbers = [5, 10, 15, 20];
const sum = numbers.reduce((accumulator, currentValue) => {
return accumulator + currentValue;
}, 0);
console.log(sum); // 50
In this example, the Array.reduce() method is used to calculate the sum of an array of numbers. The Array.reduce() method takes a callback function as an argument which takes two arguments: the accumulator and the currentValue. The accumulator is the accumulated value of the previous iterations, and the currentValue is the current element being processed. The callback function returns the accumulated value which is passed on to the next iteration. In this case, we start with an initial value of 0, and in each iteration, we add the currentValue to the accumulator.
Exercise: Objects
How can you access a property of an object in JavaScript?
const person = {
name: 'John',
age: 30,
location: 'New York'
};
// accessing a property using dot notation
console.log(person.name); // John
// accessing a property using square bracket notation
console.log(person['age']); // 30
In this example, we have an object named person with three properties: name, age, and location. To access a property of an object, we can use dot notation or square bracket notation. Dot notation is used when we know the property name at the time of coding, and square bracket notation is used when the property name is dynamic or when it contains special characters.
How can you add a new property to an object in JavaScript?
const person = {
name: 'John',
age: 30,
};
// adding a new property using dot notation
person.location = 'New York';
// adding a new property using square bracket notation
person['occupation'] = 'Software Developer';
console.log(person);
// { name: 'John', age: 30, location: 'New York', occupation: 'Software Developer' }
In this example, we have an object named person with two properties: name and age. To add a new property to an object, we can use dot notation or square bracket notation. We can assign a value to the new property using the assignment operator.
Sorting an array of objects by a specific property: Given an array of objects with various properties, sort the array based on a specific property value. For example, sort an array of objects containing employee data by their salary in descending order.
const employees = [
{ name: 'Alice', salary: 50000 },
{ name: 'Bob', salary: 60000 },
{ name: 'Charlie', salary: 45000 },
{ name: 'Dave', salary: 70000 },
];
employees.sort((a, b) => b.salary - a.salary);
console.log(employees);
// Output: [{ name: 'Dave', salary: 70000 }, { name: 'Bob', salary: 60000 }, { name: 'Alice', salary: 50000 }, { name: 'Charlie', salary: 45000 }]
Note: This is not complete solution, think and code.
Merging multiple objects into one: Given multiple objects, merge them into a single object with all the properties and values. If a property exists in multiple objects, use the value from the last object that contains that property.
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const obj3 = { c: 5, d: 6 };
const merged = Object.assign({}, obj1, obj2, obj3);
console.log(merged);
// Output: { a: 1, b: 3, c: 5, d: 6 }
Exercise: DOM
What is the Document Object Model (DOM) in JavaScript and how does it work?
Example: Suppose you have an HTML document with a button element that has an id attribute of "myButton". To access this element in JavaScript, you would use the following code:
const button = document.getElementById("myButton");
The DOM is a programming interface for web documents that allows JavaScript to interact with HTML and CSS. When a web page is loaded, the browser creates a DOM tree representing the structure of the document, and each element in the tree becomes a node in the DOM. JavaScript can then manipulate these nodes to change the content, style, and behavior of the web page.
How can you add and remove HTML elements using the DOM in JavaScript?
Example: Suppose you want to add a new paragraph element to the body of an HTML document. You can use the following code:
const newParagraph = document.createElement("p");
const textNode = document.createTextNode("This is a new paragraph.");
newParagraph.appendChild(textNode);
document.body.appendChild(newParagraph);
To remove an element from the DOM, you can use the removeChild() method. For example, to remove the first child element of the body element, you can use the following code:
const body = document.body;
const firstChild = body.firstChild;
body.removeChild(firstChild);
How can you respond to events using the DOM in JavaScript?
Example: Suppose you want to change the text of a paragraph element when a button is clicked. You can use the following code:
<button id="myButton">Click me!</button>
<p id="myParagraph">This is some text.</p>
const button = document.getElementById("myButton");
const paragraph = document.getElementById("myParagraph");
button.addEventListener("click", function() {
paragraph.textContent = "The text has changed!";
});
In this example, the addEventListener() method is used to attach a "click" event listener to the button element. When the button is clicked, the anonymous function passed as the second argument is called, which changes the text content of the paragraph element.
Exercise: Async Programming
What is asynchronous programming in JavaScript, and how does it work?
Answer: Asynchronous programming in JavaScript refers to a programming paradigm that allows multiple tasks to be executed concurrently, without blocking the main execution thread. This is achieved by using callbacks, promises, and async/await syntax in JavaScript.
Here's an example of asynchronous programming using the setTimeout function:
console.log('Start');
setTimeout(() => {
console.log('Timer done');
}, 2000);
console.log('End');
In this example, we use the setTimeout function to delay the execution of a callback function by two seconds. While the callback is waiting to be executed, the main execution thread continues running the rest of the code. When the two-second delay is up, the callback function is executed.
What are promises in JavaScript, and how do they work?
Answer: Promises in JavaScript are a way to handle asynchronous operations by representing a value that may not be available yet, but will be resolved at some point in the future. Promises have three states: pending, fulfilled, or rejected.
Here's an example of using promises in JavaScript:
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Data fetched successfully!');
}, 2000);
});
};
fetchData()
.then((data) => console.log(data))
.catch((error) => console.error(error));
In this example, we define a function called fetchData that returns a new Promise object. The Promise object is resolved after a two-second delay, and the resolved value is the string 'Data fetched successfully!'. We then call the fetchData function and use the then method to handle the fulfilled state of the Promise, and the catch method to handle the rejected state of the Promise.
What is async/await syntax in JavaScript, and how does it work?
Answer: Async/await syntax in JavaScript is a way to write asynchronous code that looks and behaves like synchronous code. Async/await is built on top of Promises, and allows you to write asynchronous code that is easier to read and understand.
Here's an example of using async/await syntax in JavaScript:
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Data fetched successfully!');
}, 2000);
});
};
const fetchDataAsync = async () => {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error(error);
}
};
fetchDataAsync();
In this example, we define a function called fetchDataAsync that uses async/await syntax to call the fetchData function and handle the result. Inside the try block, we use the await keyword to wait for the fetchData function to resolve, and then assign the resolved value to a variable called data. We then log the data variable to the console. If an error occurs, we catch it and log it to the console using the catch block.
How can you execute a set of asynchronous tasks in parallel, and wait for all of them to complete before continuing with the next step?
Answer: You can use the Promise.all method in JavaScript to execute a set of asynchronous tasks in parallel, and wait for all of them to complete before continuing with the next step.
Here's an example of using Promise.all in JavaScript:
const fetchData = (url) => {
return fetch(url)
.then((response) => response.json())
.then((data) => {
console.log(`Data fetched from ${url}`);
return data;
});
};
const urls = ['https://jsonplaceholder.typicode.com/posts', 'https://jsonplaceholder.typicode.com/comments'];
Promise.all(urls.map((url) => fetchData(url)))
.then((results) => {
console.log('All data fetched successfully!');
console.log(results);
})
.catch((error) => console.error(error));
In this example, we define a function called fetchData that fetches data from a URL using the fetch method and returns a Promise that resolves to the fetched data. We then define an array of URLs to fetch data from, and use the Promise.all method to execute the fetchData function for each URL in parallel. The Promise.all method returns a new Promise that resolves to an array of all the resolved values from the individual Promises. We then use the then method to log the array of results to the console.
How can you handle errors that occur in a chain of asynchronous operations using promises?
Answer: You can use the catch method in JavaScript to handle errors that occur in a chain of asynchronous operations using promises.
Here's an example of using the catch method in JavaScript:
const fetchData = (url) => {
return fetch(url)
.then((response) => response.json())
.then((data) => {
console.log(`Data fetched from ${url}`);
return data;
});
};
fetchData('https://jsonplaceholder.typicode.com/posts')
.then((posts) => {
return fetchData('https://jsonplaceholder.typicode.com/comments')
.then((comments) => {
console.log('All data fetched successfully!');
console.log(posts, comments);
});
})
.catch((error) => console.error(error));
In this example, we define a function called fetchData that fetches data from a URL using the fetch method and returns a Promise that resolves to the fetched data. We then call the fetchData function twice, once for the posts endpoint and once for the comments endpoint, and use the then method to chain the asynchronous operations together. We use the catch method to handle any errors that occur during the chain of asynchronous operations.
How can you convert a callback-based function to a Promise-based function in JavaScript?
Answer: You can use the util.promisify method in Node.js to convert a callback-based function to a Promise-based function in JavaScript.
Here's an example of using the util.promisify method in JavaScript
const fs = require('fs');
const { promisify } = require('util');
const readFileAsync = promisify(fs.readFile);
readFileAsync('file.txt', 'utf-8')
.then((data) => console.log(data))
.catch((error) => console.error(error));
Backend Development: The Node, The Express And The API
Introduction to backend
We need a backend to handle all the behind-the-scenes work of a website or application. It's like the engine of a car – you don't see it, but it powers everything.
Backend is needed for tasks like:
- Storing and retrieving data from databases.
- Processing and handling user requests.
- Implementing business logic and rules.
- Managing security and user authentication.
- Integrating with other services and APIs.
In short, the backend makes sure that everything works smoothly and efficiently, allowing the frontend to focus on providing a great user experience.
Why do we need backend?
Let's explain the concept of backend in layman's terms:
-
Imagine you're visiting a restaurant. The frontend is like the menu you're given to choose your food from. It's nicely designed, colorful, and easy to read. You pick what you want to eat and give your order to the waiter.
-
Now, the waiter takes your order to the kitchen, where all the cooking happens. The kitchen is like the backend of a website or application. It's where the magic really happens. The chefs (or backend developers) receive your order, prepare the food, and then send it back out to you.
-
Similarly, in the world of technology, the frontend is what you see and interact with on your screen – the buttons, images, and text. But when you click a button or submit a form, that information needs to be processed, saved, or retrieved from somewhere. That's where the backend comes in.
-
The backend consists of servers, databases, and applications that work behind the scenes to make everything happen. It's responsible for processing your requests, handling data, and sending responses back to the frontend.
-
So, in simple terms, we need a backend to handle the "cooking" – processing requests, managing data, and making sure everything runs smoothly – so that the frontend can focus on looking good and providing a great user experience.
NodeJS
Node.js is an open-source, cross-platform JavaScript runtime environment that executes JavaScript code outside of a web browser. It allows developers to use JavaScript to build server-side and networking applications.
The role of Node.js in the backend is to handle server-side logic, manage data, and process requests and responses in web applications. Some key roles of Node.js in the backend include:
-
Server-side JavaScript execution: Node.js allows developers to write server-side code in JavaScript, enabling them to use the same language for both frontend and backend development.
-
Non-blocking I/O: Node.js uses an event-driven, non-blocking I/O model, which makes it lightweight and efficient for handling multiple connections simultaneously. This allows Node.js applications to handle a large number of concurrent requests without blocking the execution of other operations.
-
Building scalable applications: Node.js is well-suited for building scalable and high-performance applications due to its non-blocking I/O model and event-driven architecture. It allows developers to easily scale their applications to handle increasing loads by adding more servers or utilizing clustering techniques.
-
Access to a rich ecosystem of packages: Node.js has a vast ecosystem of open-source packages available through npm (Node Package Manager). These packages provide ready-made solutions for various backend tasks, such as web frameworks, database drivers, authentication libraries, and more, allowing developers to quickly build and extend their applications.
Overall, Node.js plays a crucial role in modern backend development by enabling developers to build fast, scalable, and efficient web applications using JavaScript.
What is Non-blocking I/O?
Let's break down non-blocking I/O in layman's terms:
-
Imagine you're waiting in line at a coffee shop to order your favorite drink. In a traditional, blocking I/O scenario, you'd have to wait until the person in front of you finishes ordering before you can place your order. Everyone has to wait their turn, and if someone takes a long time, it slows down the entire line.
-
Now, let's consider a non-blocking I/O scenario. Instead of waiting in line, you grab a number and can continue doing other things while you wait for your turn. You're not stuck waiting for the person in front of you to finish – you're free to multitask and be productive.
-
In the context of software, non-blocking I/O works similarly. When an application performs an I/O operation (like reading data from a file or fetching data from a database), it doesn't wait for the operation to complete before moving on to the next task. Instead, it continues executing other tasks or processing requests while waiting for the I/O operation to finish.
-
This non-blocking approach allows the application to remain responsive and handle multiple tasks simultaneously without getting stuck waiting for one task to complete. It's like being able to do other things while waiting in line – you're not blocked or slowed down by one task, and you can make better use of your time.
Installation guide for NodeJS
Following are the step-by-step instructions to set up Node.js on both Windows and Linux:
Windows
-
Download Node.js Installer:
- Visit the official Node.js website: https://nodejs.org/
- Download the Windows installer (.msi file) for the LTS (Long-Term Support) version or the latest version.
-
Run Node.js Installer:
- Once the installer is downloaded, double-click on the .msi file to run it.
- Follow the prompts in the installer wizard to complete the installation.
- Accept the license agreement, choose the installation directory, and click "Next" to proceed.
-
Verify Installation:
- After the installation is complete, open Command Prompt (or PowerShell).
- Using Command Prompt is recommended. (Better use Linux/Ubuntu)
- Type the following command and press Enter:
node -v
- This command should print the installed Node.js version. Similarly, you can check the installed npm version using:
npm -v
Linux (Ubuntu/Debian)
- Install Node.js using Package Manager:
- Open a terminal window.
- For Ubuntu/Debian-based distributions, use the following commands to install Node.js:
- These commands will update the package index and install Node.js along with npm (Node Package Manager).
sudo apt update
sudo apt install nodejs npm
- Verify Installation:
- After the installation is complete, you can verify Node.js and npm versions by running the following commands in the terminal:
node -v
npm -v
macOS
- Install Node.js using Homebrew:
- Open Terminal, which you can find in the "Utilities" folder within the "Applications" folder, or by searching for it in Spotlight (Cmd + Space, then type "Terminal").
- Install Homebrew if you haven't already. You can do this by running the following command:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- Once Homebrew is installed, you can use it to install Node.js. Run the following command:
brew install node
- Verify Installation:
- After the installation is complete, you can verify Node.js and npm versions by running the following commands in Terminal:
node -v
npm -v
Note: current commands may vary from the commands mentioned above due to updates, check the latest guide available from the internet.
Writing "Hello World" in Node.js
-
Create a New File:
- Open your preferred text editor (e.g., Visual Studio Code, Sublime Text, or Notepad).
- Create a new file and name it hello.js.
-
Write the Code:
- Inside the hello.js file, write the following JavaScript code:
console.log("Hello World!");
- Save the File:
- Save the hello.js file in a location of your choice.
Running Node.js Code
Now, let's see how to run the Node.js code:
-
Open Terminal/Command Prompt:
- Open Terminal (macOS/Linux) or Command Prompt (Windows).
-
Navigate to the Directory:
- Use the cd command to navigate to the directory where you saved the hello.js file. For example:
cd path/to/directory
- Run the Node.js Code:
- Once you're in the correct directory, run the following command in Terminal/Command Prompt:
node hello.js
- View Output:
- After executing the command, you should see the output "Hello World!" printed in the Terminal/Command Prompt.
Explanation:
-
The console.log() function is used in Node.js to print messages to the console. In the code console.log("Hello World!");, "Hello World!" is the message that will be printed to the console.
-
When you run the command node hello.js, Node.js executes the JavaScript code in the hello.js file, and the output is displayed in the Terminal/Command Prompt.
-
That's it! You've successfully written a "Hello World" program in Node.js and learned how to run it. You can now experiment with writing more complex Node.js applications and running them using the same process.
Basics in NodeJS
What is Node Js actually ?
- Node JS is not a language it is a runtime environment, just like how we run JS in Browser Environment.
- It is a tool, we use it build any projects but code in JS.
- Under the hood of any Browser, there is a engine that runs JS code, for example :
- V8 engine for Google Chrome
- SpiderMonkey for Mozilla
- JSCore for Safari
- Chakra for Internet Explorer and now V8 for Edge
- Similarly Node uses V8 engine to run JS code outside of the Browser, additionally it uses few libraries and C++ bindings for internal process communication.
How does Node.js work?
-
Node.js is a JavaScript Runtime:
- Node.js is an open-source, cross-platform JavaScript runtime environment. It allows you to run JavaScript code outside of a web browser, on servers or local machines.
-
Event-Driven and Non-Blocking I/O:
- Node.js uses an event-driven, non-blocking I/O model. This means that instead of waiting for tasks to complete before moving on to the next one, Node.js can handle multiple tasks simultaneously without blocking the execution of other operations.
-
Single-Threaded Event Loop:
- Node.js operates on a single-threaded event loop. This event loop continuously listens for events and executes callback functions when events occur. It efficiently handles I/O operations by delegating them to the operating system, allowing the main thread to remain responsive.
-
Asynchronous Programming:
- In Node.js, most I/O operations, such as file system operations, network requests, and database queries, are performed asynchronously. This means that the program does not wait for these operations to complete before moving on to the next task. Instead, callback functions are used to handle the results of asynchronous operations when they are ready.
What is V8 Engine for Node.js?
-
JavaScript Engine:
- The V8 engine is an open-source JavaScript engine developed by Google. It is written in C++ and is used to execute JavaScript code in web browsers and other environments.
-
Optimized for Performance:
- The V8 engine is designed to optimize the execution of JavaScript code for performance. It uses various techniques, such as just-in-time (JIT) compilation and optimization of JavaScript code, to make execution faster and more efficient.
-
Used in Node.js:
- Node.js leverages the V8 engine to execute JavaScript code outside of web browsers. When you run a Node.js application, the V8 engine compiles and executes the JavaScript code, making it possible to build fast and efficient server-side applications using JavaScript.
-
Integration with Node.js:
- Node.js integrates the V8 engine into its runtime environment, allowing developers to write server-side JavaScript code that can take advantage of the performance optimizations provided by the V8 engine.
In summary, Node.js uses the V8 engine to execute JavaScript code efficiently on servers or local machines. The V8 engine is a key component of Node.js, enabling it to deliver high-performance and scalable server-side applications.
How does NodeJS executes a code using V8 engine?
-
Parsing JavaScript Code:
- When you run a Node.js application, the JavaScript code is first parsed by the Node.js runtime environment.
-
Compilation by V8 Engine:
- Once the code is parsed, it is handed over to the V8 engine for compilation. The V8 engine compiles the JavaScript code into machine code, which can be executed by the underlying hardware.
-
Execution of Machine Code:
- The compiled machine code is then executed by the CPU. This is where the actual execution of the JavaScript code takes place.
-
Event Loop and Asynchronous Operations:
- While the JavaScript code is being executed, Node.js manages asynchronous operations using its event loop mechanism. Asynchronous tasks, such as I/O operations, timers, and callbacks, are scheduled and executed by the event loop, allowing the main thread to remain responsive.
-
Handling I/O Operations:
- When an asynchronous I/O operation is encountered, such as reading from a file or making a network request, Node.js delegates the operation to the underlying operating system, which handles it asynchronously. Once the operation is completed, a callback function is executed to handle the result.
-
Returning Results:
- As the JavaScript code executes, results are returned to the calling code or passed to callback functions as needed. This allows the program to continue executing and processing data as it becomes available.
In summary, Node.js leverages the V8 engine to compile and execute JavaScript code efficiently. The V8 engine compiles JavaScript code into machine code, which is then executed by the CPU. Node.js manages asynchronous operations using its event loop mechanism, ensuring that the main thread remains responsive while handling I/O operations and executing callback functions.
More about NodeJS architecture:
Let’s delve into the major components of the Node.js V8 Engine and their roles:
-
V8 Engine:
- Role: The V8 engine is the heart of Node.js. It’s responsible for executing JavaScript code efficiently.
- Composition: V8 is written in approximately 30% JavaScript and 70% C++.
Functionality:
- Just-In-Time (JIT) Compilation: V8 translates JavaScript code into machine code at runtime, optimizing execution speed.
- Memory Management: It handles memory allocation and garbage collection.
- ECMAScript Compatibility: V8 ensures compatibility with ECMAScript standards.
- Performance Optimization: V8 optimizes code execution by using techniques like inline caching and hidden classes.
-
libuv:
- Role: libuv is a cross-platform library that provides asynchronous I/O operations and event-driven programming.
- Composition: It’s entirely written in C++.
- Functionality:
- Event Loop: libuv manages the event loop, allowing Node.js to handle non-blocking tasks efficiently.
- File System Operations: It provides APIs for file I/O, directory operations, and file watching.
- Network Operations: libuv handles network sockets, DNS resolution, and other network-related tasks.
- Child Processes: It manages child processes, enabling parallel execution.
- Timers and Callbacks: libuv schedules timers and callbacks for asynchronous operations.
These components work together to make Node.js powerful, efficient, and suitable for building scalable applications. 🚀
What is npm?
npm stands for Node Package Manager. In simple terms, npm is a tool that helps developers manage and share JavaScript code packages or libraries.
Here's how npm works:
-
Package Management:
- npm allows developers to easily install, manage, and update JavaScript packages or libraries (also known as "packages" or "modules") for their projects. These packages contain reusable code that can perform specific tasks or provide functionality, such as handling HTTP requests, working with databases, or implementing user interfaces.
-
Dependency Management:
- When a developer installs a package using npm, it automatically handles any dependencies required by that package. This means that npm will also download and install any other packages that the main package depends on, ensuring that all necessary code is available for the project to function correctly.
-
Version Control:
- npm also provides version control for packages. Each package has a version number, and developers can specify which version of a package they want to install in their project. This allows developers to ensure that their projects use the correct version of a package and avoid compatibility issues with newer or older versions.
-
Publishing and Sharing:
- Developers can publish their own JavaScript packages to the npm registry, making them available for other developers to use in their projects. This allows developers to share their code with the community and contribute to the ecosystem of open-source JavaScript libraries.
In summary, npm is a powerful tool that simplifies the process of managing, installing, and sharing JavaScript code packages or libraries. It helps developers streamline their development workflow and leverage the vast ecosystem of available packages to build robust and feature-rich applications.
How to use NPM in NodeJS Project?
To use npm in a Node.js project, follow these steps:
- Initialize a Node.js project:
- Open your terminal or command prompt.
- Navigate to the directory where you want to create your Node.js project.
- Run the following command to initialize a new Node.js project:
npm init -y
This command will create a package.json file in your project directory, which will store information about your project and its dependencies.
- Install npm packages:
- To install npm packages for your project, use the npm install command followed by the name of the package you want to install.
- For example, to install the Express.js framework, run the following command:
npm install express
This command will download and install the Express.js package and its dependencies into your project's node_modules directory.
- Save dependencies to package.json:
- By default, npm will save installed packages as dependencies in your package.json file.
- If you want to save a package as a development dependency (e.g., for testing or development purposes), use the --save-dev flag.
- For example, to install the mocha testing framework as a development dependency, run the following command:
npm install mocha --save-dev
- Use installed packages in your code:
- Once the packages are installed, you can use them in your Node.js code.
- For example, if you installed Express.js, you can create a new Express application in a JavaScript file like this:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
- Run your Node.js project:
- After installing npm packages and writing your code, you can run your Node.js project using the node command followed by the filename of your main JavaScript file.
- For example, if your main file is named app.js, you can run it with the following command:
node app.js
That's it! You've successfully used npm in your Node.js project to install packages and manage dependencies. You can now continue building and developing your Node.js application using npm.
Note:
npm init
by running this command, npm will ask few straightforward question regarding the project details.
Modules Fundamentals
What are modules in NodeJS?
In Node.js, a module is essentially a JavaScript file that contains code, functions, objects, or values that can be used in other parts of your application. Modules help in organizing code into reusable parts, making it easier to maintain and understand. They also help in managing dependencies and avoiding naming conflicts.
How Modules Work in Node.js
-
Exporting: A module can export functions, objects, or values that it defines, making them available to other modules. This is done using the module.exports or exports object.
-
Importing: Other modules can import and use the exported members of a module by using the require() function.
Inbuilt Modules in Node.js
Node.js comes with a set of built-in modules that provide various functionalities without needing to install any additional packages. These modules are part of the Node.js runtime and can be used directly in your applications. Some of the most commonly used inbuilt modules include:
-
fs (File System): Provides functions to work with the file system, such as reading from and writing to files.
-
http: Allows Node.js to transfer data over the HTTP protocol. It can be used to create HTTP servers and clients.
-
path: Offers utilities for working with file and directory paths.
-
os: Provides information about the operating system, such as the operating system's name, version, and architecture.
-
events: Implements the EventEmitter class, which is used to handle events within Node.js applications.
-
util: Contains utility functions, such as inherits for prototype inheritance and format for string formatting.
-
process: Provides information about, and control over, the current Node.js process. It can be used to read environment variables, exit the process, and more.
-
stream: Provides the foundation for all streaming APIs in Node.js, allowing data to be read from and written to in a non-blocking manner.
Simplified Explanation of Module:
Imagine you're building a house. Each room (module) in the house has a specific purpose (e.g., kitchen for cooking, bedroom for sleeping). The inbuilt modules in Node.js are like the basic furniture and appliances that come with the house, allowing you to perform essential tasks without needing to buy or build everything from scratch.
In the context of Node.js, these modules are like the basic tools and utilities that come with the Node.js runtime, enabling you to perform common tasks like file operations, network communication, and more, without needing to write all the code from scratch.
Moduel: File System
We will use inbuilt file system module of nodeJS to read file by 2 different techniques:
Creating file reader functionality in Node.js can be achieved using both callbacks and promises. Let's start by implementing file reading using callbacks and then using promises. We'll use the fs module, which is a built-in module in Node.js for file system operations.
- Using Callbacks
- In Node.js, a callback is a function passed as an argument to another function, which is then invoked inside the outer function to complete some kind of routine or action.
- Step 1: Import the fs module
const fs = require('fs');
- Step 2: Implement the file reading functionality using a callback
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log('File content:', data);
});
In this example, fs.readFile is used to read the file example.txt. The second argument 'utf8' specifies the encoding. The third argument is a callback function that takes two parameters: err and data. If an error occurs during the file reading process, err will contain the error object, and data will be undefined. If the file is read successfully, err will be null, and data will contain the file content as a string.
- Using Promises
- Promises in JavaScript represent the eventual completion (or failure) of an asynchronous operation and its resulting value.
- Step 1: Import the fs module
const fs = require('fs').promises;
Note: We're using fs.promises here to work with promises.
- Step 2: Implement the file reading functionality using promises
fs.readFile('example.txt', 'utf8')
.then(data => {
console.log('File content:', data);
})
.catch(err => {
console.error('Error reading file:', err);
});
In this example, fs.readFile returns a promise that resolves with the file content if the file is read successfully. We use .then() to handle the resolved value (the file content) and .catch() to handle any errors that occur during the file reading process.
Differences Between Callbacks and Promises
- Syntax and Structure: Callbacks are functions passed as arguments to another function, while promises are objects that represent the eventual completion of an asynchronous operation.
- Error Handling: With callbacks, errors are handled in the callback function itself. With promises, errors are handled in a .catch() block, which makes error handling more consistent and centralized.
- Chaining: Promises can be chained together using .then(), allowing for more complex asynchronous operations to be performed in a more readable and maintainable way. Callbacks can lead to callback hell when dealing with multiple asynchronous operations.
- Readability and Maintainability: Promises, with their .then() and .catch() methods, can lead to more readable and maintainable code, especially when dealing with multiple asynchronous operations.
- Error Propagation: In promises, errors are propagated down the chain until they are caught by a .catch() block. This makes it easier to handle errors in a centralized manner. With callbacks, error handling needs to be done in each callback function, which can lead to repetitive and error-prone code.
In summary, while both callbacks and promises can be used for asynchronous operations in Node.js, promises offer a more modern, powerful, and readable approach to handling asynchronous operations.
Following table will give better understanding of asynchronous options in NodeJS
Feature | Callbacks | Promises | ||
---|---|---|---|---|
Structure | Nested functions | Single Promise object with .then() and .catch() methods | ||
Readability | Less readable with nested callbacks | More readable and easier to follow | ||
Error Handling | Requires manual error checking | Built-in error handling with .catch() |
Modules: http (server)
Creating a basic server in Node.js using the http module involves a few simple steps. We'll focus on handling GET and POST requests without performing any specific operations, just to demonstrate how to set up the server and handle these requests.
Step 1: Import the http Module First, you need to import the http module, which is a built-in module in Node.js for creating HTTP servers.
const http = require('http');
Step 2: Create the Server Next, you create the server using the http.createServer() method. This method takes a callback function as an argument, which is called whenever a request is received by the server. The callback function itself takes two arguments: a request object (req) and a response object (res).
const server = http.createServer((req, res) => {
// Handle the request here
});
Step 3: Handle GET Requests Inside the callback function, you can check the request method to determine if it's a GET request. If it is, you can send a response back to the client.
if (req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, this is a GET request!\n');
}
Step 4: Handle POST Requests Similarly, you can check for POST requests and handle them accordingly. For simplicity, we'll just acknowledge the POST request without performing any operations on the data sent.
if (req.method === 'POST') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, this is a POST request!\n');
}
Step 5: Start the Server Finally, you need to start the server by calling the listen() method on the server object. This method takes a port number as an argument and optionally a hostname.
const port = 3000;
server.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
Complete Example Here's the complete code for a basic server that handles GET and POST requests:
const http = require('http');
const server = http.createServer((req, res) => {
if (req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, this is a GET request!\n');
} else if (req.method === 'POST') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, this is a POST request!\n');
}
});
const port = 3000;
server.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
Explanation
- Importing the http Module: This is the first step where you make the http module available in your script.
- Creating the Server: You create a server that listens for incoming requests. The callback function is where you define how to handle these requests.
- Handling GET and POST Requests: Inside the callback, you check the request method. If it's a GET request, you send a simple response. If it's a POST request, you send a different response.
- Starting the Server: Finally, you start the server on a specific port. Once the server is running, it listens for incoming requests and handles them based on the logic you've defined.
This basic server setup is a starting point for building more complex applications in Node.js.
REST API: http (server)
What is REST Concept/Architecture?
REST, which stands for Representational State Transfer, is a set of architectural principles for designing networked applications. It's a way to structure your application so that it can be easily understood and used by other applications. In simple terms, REST is like a set of rules for how different parts of a web application should talk to each other.
Key Concepts of REST:
-
Resources: In REST, everything is a resource. A resource can be anything that can be named and addressed, such as a document, an image, a temporal service, a collection of other resources, a non-virtual object, and so on. In the context of a web application, resources are often represented by URLs.
-
HTTP Methods: REST uses standard HTTP methods to perform operations on resources. The most common methods are GET (retrieve a resource), POST (create a new resource), PUT (update an existing resource), and DELETE (remove a resource).
-
Stateless: Each request from a client to a server must contain all the information needed to understand and process the request. The server should not store anything about the latest HTTP request the client made. Each request is processed independently.
-
Client-Server Architecture: The client is responsible for the user interface and user experience, and the server is responsible for processing requests and managing resources. The client and server communicate over HTTP, and they can be developed independently as long as they adhere to the same interface.
-
Cacheable: Responses from the server can be cached by the client. This can improve performance by reducing the need for repeated requests for the same data.
Adding Resources/URLs to the Server created in previous page
To demonstrate REST principles, let's add a simple resource to our server. We'll create a resource named "message" that can be accessed via a URL.
Step 1: Define the Resource URL We'll use the URL path /message to represent our "message" resource.
Step 2: Update the Server to Handle the Resource We'll modify the server to handle GET and POST requests specifically for the /message resource.
const http = require('http');
const server = http.createServer((req, res) => {
const url = req.url;
if (req.method === 'GET' && url === '/message') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('This is the GET response for the /message resource.\n');
} else if (req.method === 'POST' && url === '/message') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('This is the POST response for the /message resource.\n');
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found\n');
}
});
const port = 3000;
server.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
Explanation
-
Resource URL: We've defined /message as the URL for our "message" resource. This is how clients will access this resource.
-
Handling GET and POST Requests: The server checks if the request is for the /message resource and if it's a GET or POST request. It then sends a response specific to the request method.
-
404 Response: If the request is not for the /message resource or if it's not a GET or POST request, the server sends a 404 Not Found response.
This simple example demonstrates how to structure a server to follow REST principles by defining resources and handling them with specific HTTP methods.
Assignments
Create projects on the following of the topics, create at least one project from the given options per assignment number. You can follow the guide provided for each of the project topics by your mentor.
A submission form will be circulated.
Assignment 1: Dealing with HTML & CSS
Create project on any of the following topics:
- A. Dice Game UI
- B. Create a block having :
- 1. Input field
-
- 4 buttons (+1 , -1 , +10, -10)
- (Value of the number should be Incremented the number of times the value present on the button when a button is pressed )
- C. Portfolio website
Assignment 2: Dealing with JavaScript & React Basics
- A. Make API Calls in JavaScript.
- B. Convert your HTML and CSS project into React
- C. Todo App in JavaScript
Assignment 3: Dealing with React
- A Drill down props from parent to child in React.
- B. Fetch data from API in React
- Use the following API to fetch the data "https://restcountries.com/v3.1/all"
- Show this data in the form of Cards
Dice Game UI
Overview
In this project, we will create a simple user interface (UI) for a dice game using HTML and CSS. The UI will consist of dice images and a button to roll the dice. The goal is to provide a visually appealing interface for users to interact with while playing the dice game.
Modify the project as per your mentor's instructions.
Project Structure:]
- HTML File (index.html): Contains the structure of the webpage.
- CSS File (styles.css): Contains the styles to customize the appearance of the webpage.
- Dice Images: Images of dice faces (e.g., dice1.png, dice2.png, etc.) to display on the UI.
Steps to Create the Dice Game UI:
Step 1: Set Up HTML Structure
Create an HTML file named index.html.
Define the basic structure of the webpage using HTML tags such as <html>, <head>, <body>, and <div>
.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dice Game</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1>Dice Game</h1>
<div class="dice"></div>
<button class="roll-btn">Roll Dice</button>
</div>
</body>
</html>
Step 2: Style the UI Using CSS
Create a CSS file named styles.css. Style the container, dice, and button elements to enhance the appearance of the UI.
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
text-align: center;
}
.dice {
width: 150px;
height: 150px;
background-image: url('dice.png'); /* Replace 'dice.png' with the path to your dice image */
background-size: cover;
margin: 20px auto;
}
.roll-btn {
padding: 10px 20px;
font-size: 18px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.roll-btn:hover {
background-color: #0056b3;
}
Step 3: Add Dice Images
Download or create images of dice faces (e.g., dice1.png, dice2.png, etc.). Place the dice images in the same directory as your HTML file.
Step 4: Final Touches
Open the index.html file in a web browser to view the Dice Game UI. Click the "Roll Dice" button to roll the dice and see the result.
This simple Dice Game UI will provide users with a visually appealing interface to roll the dice and enjoy the game.
Create a counter block
Project Idea
Create a block having :
- Input field
- 4 buttons (+1 , -1 , +10, -10)
- (Value of the number should be Incremented the number of times the value present on the button when a button is pressed )
Here's a sample HTML and CSS block with an input field and four buttons:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Number Incrementer</title>
<style>
.container {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 50px;
}
input {
width: 200px;
padding: 10px;
margin-bottom: 20px;
font-size: 16px;
text-align: center;
}
button {
width: 100px;
padding: 10px;
margin: 5px;
font-size: 16px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<input type="number" id="numberInput" value="0" readonly>
<button onclick="increment(1)">+1</button>
<button onclick="increment(-1)">-1</button>
<button onclick="increment(10)">+10</button>
<button onclick="increment(-10)">-10</button>
</div>
<script>
function increment(value) {
const numberInput = document.getElementById('numberInput');
let currentValue = parseInt(numberInput.value);
currentValue += value;
numberInput.value = currentValue;
}
</script>
</body>
</html>
This HTML code creates a block with an input field and four buttons. The buttons allow you to increment the value in the input field by either 1, -1, 10, or -10 each time they are clicked. The value in the input field is updated accordingly using JavaScript.
Portfolio Using HTML and CSS
Introduction
Building a portfolio website is a great way to showcase your skills, projects, and achievements to potential employers or clients. In this project, we'll walk through the steps to create a simple portfolio website using HTML and CSS.
Prerequisites
Basic knowledge of HTML and CSS.
Project Overview
We'll create a portfolio website with multiple sections, including:
- Home (Introduction)
- About Me
- Projects
- Contact
- Each section will have its own layout and content to showcase different aspects of your portfolio.
Steps to Build the Portfolio
Step 1: Set Up Your Project
Create a new folder for your project and set up the basic structure with the following files:
index.html: Main HTML file. styles.css: CSS stylesheet for styling.
Step 2: Design the Layout
Define the layout of your portfolio website using HTML. Use semantic HTML elements to structure different sections of the website, such as <header>, <nav>, <main>, <section>, and <footer>
. You can also include links to external CSS frameworks like Bootstrap for faster development.
Step 3: Style Your Portfolio
Apply CSS styles to make your portfolio visually appealing. Use CSS for layout, typography, colors, and spacing. You can create custom styles or use CSS frameworks like Bootstrap or Bulma for pre-designed components and layouts.
Step 4: Populate Content
Add content to each section of your portfolio, including information about yourself, your skills, projects you've worked on, and how to contact you. Use headings, paragraphs, lists, and images to organize and present your content effectively.
Step 5: Test and Refine
Test your portfolio website across different devices and web browsers to ensure that it looks and functions correctly. Make any necessary adjustments to improve the overall user experience and responsiveness of the website.
Example Code: HTML (index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Portfolio</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>My Portfolio</h1>
<nav>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#projects">Projects</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</header>
<main>
<section id="home">
<h2>Welcome to My Portfolio</h2>
<p>Hi, I'm [Your Name], a web developer based in [Your Location].</p>
</section>
<section id="about">
<h2>About Me</h2>
<p>I have experience in HTML, CSS, JavaScript, and other web technologies. I enjoy building responsive and user-friendly websites.</p>
</section>
<section id="projects">
<h2>Projects</h2>
<div class="project">
<h3>Project 1</h3>
<p>Description of Project 1.</p>
</div>
<div class="project">
<h3>Project 2</h3>
<p>Description of Project 2.</p>
</div>
</section>
<section id="contact">
<h2>Contact Me</h2>
<p>You can reach me at [Your Email Address].</p>
</section>
</main>
<footer>
<p>© 2023 My Portfolio. All rights reserved.</p>
</footer>
</body>
</html>
/* Reset styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
}
header {
background: #333;
color: #fff;
padding: 20px;
}
nav ul {
list-style: none;
}
nav ul li {
display: inline;
margin-right: 20px;
}
nav ul li a {
color: #fff;
text-decoration: none;
}
main {
padding: 20px;
}
section {
margin-bottom: 20px;
}
footer {
background: #333;
color: #fff;
text-align: center;
padding: 10px 0;
}
Creating a portfolio website using HTML and CSS is a great way to showcase your skills and projects to potential employers or clients. By following the steps outlined in this project guide and customizing the design and content to fit your needs, you can create an impressive portfolio that effectively highlights your accomplishments as a web developer.
Make API Calls and Show User Details
Introduction
In this project, we will create a simple web application that makes API calls to fetch user details from a public API and displays them on the webpage. We'll use HTML, CSS, and JavaScript to build the frontend of the application.
Prerequisites
Basic knowledge of HTML, CSS, and JavaScript. Access to a public API that provides user data (e.g., JSONPlaceholder).
Project Overview
We'll build a single-page web application with the following features:
- Input field to enter the user ID.
- Button to trigger the API call.
- Display area to show the user details fetched from the API.
Steps to Build the Project
Step 1: Set Up Your Project
Create a new folder for your project and set up the basic structure with the following files:
- index.html: Main HTML file.
- styles.css: CSS stylesheet for styling.
- script.js: JavaScript file for handling API calls and DOM manipulation.
Step 2: Design the Layout
Define the layout of your web application using HTML. Use semantic HTML elements to structure different sections of the webpage, such as <header>, <main>, <section>, and <footer>
. Add input fields, buttons, and display areas as needed.
Step 3: Style Your Web Application
Apply CSS styles to make your web application visually appealing. Use CSS for layout, typography, colors, and spacing. You can create custom styles or use CSS frameworks like Bootstrap or Bulma for pre-designed components and layouts.
Step 4: Make API Calls
Write JavaScript code to make API calls to fetch user details from the public API. You can use the fetch() function or libraries like Axios to make HTTP requests. Parse the response data (usually in JSON format) and extract the relevant user details.
Step 5: Display User Details
Update the DOM dynamically with the user details fetched from the API. Use JavaScript to manipulate the DOM and display the user details in the designated display area on the webpage.
Step 6: Test and Refine
Test your web application by entering different user IDs and verifying that the user details are fetched and displayed correctly. Make any necessary adjustments to improve the user experience and responsiveness of the application.
Example Code:
HTML (index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User Details</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>User Details</h1>
</header>
<main>
<section>
<label for="userId">Enter User ID:</label>
<input type="text" id="userId" placeholder="Enter user ID...">
<button onclick="fetchUserDetails()">Get Details</button>
</section>
<section id="userDetails">
<!-- User details will be displayed here -->
</section>
</main>
<footer>
<p>© 2023 User Details. All rights reserved.</p>
</footer>
<script src="script.js"></script>
</body>
</html>
CSS (styles.css):
/* Reset styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
background-color: #f4f4f4;
}
header {
background: #333;
color: #fff;
padding: 20px;
text-align: center;
}
main {
padding: 20px;
}
section {
margin-bottom: 20px;
}
input[type="text"] {
padding: 10px;
font-size: 16px;
border: 1px solid #ccc;
width: 200px;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
background-color: #333;
color: #fff;
border: none;
}
button:hover {
background-color: #555;
}
#userDetails {
background: #fff;
padding: 20px;
}
JavaScript (script.js):
function fetchUserDetails() {
const userId = document.getElementById('userId').value;
fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
.then(response => response.json())
.then(user => {
displayUserDetails(user);
})
.catch(error => {
console.error('Error fetching user details:', error);
});
}
function displayUserDetails(user) {
const userDetailsSection = document.getElementById('userDetails');
userDetailsSection.innerHTML = `
<h2>User Details</h2>
<p><strong>Name:</strong> ${user.name}</p
Convert your HTML and CSS project into React
Step 1: Set Up Your React Environment
Make sure you have Node.js installed on your system. Use Create React App to set up your project. Run the following command in your terminal:
npx create-react-app todo-app
Navigate into the project directory:
cd todo-app
Start the development server:
npm start
Step 2: Create Components
Inside the src folder, create a new folder named components. Create a new file named Todo.js inside the components folder. Open Todo.js and create a functional component for Todo items.
Step 3: Define State and Event Handlers
In the src folder, open App.js. Define state to manage the list of Todo items. Write event handlers to add, delete, and toggle Todo items.
Step 4: Render Todo List
Inside the render method of App.js, map through the list of Todo items and render each Todo component. Pass necessary props (e.g., Todo text, completion status) to the Todo component.
Step 5: Implement Add Todo Functionality
Create an input field and a button in the App component for adding new Todo items. Write a function to handle adding new Todo items to the list.
Step 6: Implement Delete and Toggle Functionality
Add delete and toggle buttons to each Todo item component. Write functions to handle deleting and toggling Todo items.
Step 7: Styling
Use CSS to style your Todo App components. Make it visually appealing by adding colors, fonts, and layout adjustments.
Extra Features
- Local Storage: Implement local storage to persist Todo items between page refreshes.
- Filtering: Add filtering options to filter Todo items based on completion status (e.g., all, active, completed).
- Edit Todo: Allow users to edit existing Todo items.
- Clear Completed: Add a button to clear all completed Todo items from the list.
- Multiple Lists: Allow users to create multiple Todo lists/categories.
- Drag and Drop: Implement drag and drop functionality to reorder Todo items.
- Themes: Allow users to choose from different themes for the Todo App.
Example code for the Todo App in React, along with additional features like local storage and filtering
Todo.js Component
import React from 'react';
const Todo = ({ todo, toggleTodo, deleteTodo }) => {
return (
<div className={`todo ${todo.completed ? 'completed' : ''}`}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<p>{todo.text}</p>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
</div>
);
};
export default Todo;
App.js Component
import React, { useState, useEffect } from 'react';
import Todo from './components/Todo';
import './App.css';
const App = () => {
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodo] = useState('');
useEffect(() => {
const storedTodos = JSON.parse(localStorage.getItem('todos'));
if (storedTodos) {
setTodos(storedTodos);
}
}, []);
useEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos));
}, [todos]);
const addTodo = () => {
if (newTodo.trim() === '') return;
const newTodoItem = {
id: Date.now(),
text: newTodo,
completed: false,
};
setTodos([...todos, newTodoItem]);
setNewTodo('');
};
const toggleTodo = (id) => {
const updatedTodos = todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
);
setTodos(updatedTodos);
};
const deleteTodo = (id) => {
const updatedTodos = todos.filter((todo) => todo.id !== id);
setTodos(updatedTodos);
};
return (
<div className="App">
<h1>Todo App</h1>
<input
type="text"
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
placeholder="Add new todo..."
/>
<button onClick={addTodo}>Add Todo</button>
<div className="todo-list">
{todos.map((todo) => (
<Todo
key={todo.id}
todo={todo}
toggleTodo={toggleTodo}
deleteTodo={deleteTodo}
/>
))}
</div>
</div>
);
};
export default App;
App.css
.App {
text-align: center;
margin-top: 50px;
}
.todo {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.todo.completed {
text-decoration: line-through;
}
input[type='checkbox'] {
margin-right: 10px;
}
.todo-list {
margin-top: 20px;
}
button {
margin-left: 10px;
}
Todo App UI using HTML and CSS
Overview
In this project, we will create a simple Todo App User Interface (UI) using HTML and CSS. The Todo App will allow users to add tasks, mark tasks as completed, and delete tasks. We'll focus on creating a clean and intuitive interface that is easy to use.
Steps
Setup
Create a new folder for your project and create two files: index.html and styles.css.
HTML Structure
Open index.html and set up the basic structure of the Todo App UI using HTML tags. Here's a simple example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Todo App</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1>Todo App</h1>
<div class="todo-list">
<input type="text" placeholder="Add a new task">
<button>Add Task</button>
<ul>
<!-- Todo tasks will be dynamically added here -->
</ul>
</div>
</div>
</body>
</html>
CSS Styling
Open styles.css and add CSS rules to style the Todo App UI. Here's an example to get started:
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.container {
max-width: 600px;
margin: 20px auto;
padding: 20px;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
h1 {
text-align: center;
}
.todo-list {
margin-top: 20px;
}
input[type="text"] {
width: 70%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
margin-right: 10px;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
}
ul {
list-style-type: none;
padding: 0;
}
li {
background-color: #f9f9f9;
padding: 10px;
margin-top: 10px;
border-radius: 5px;
}
li.completed {
text-decoration: line-through;
background-color: #d3d3d3;
}
.delete-btn {
background-color: #dc3545;
color: #fff;
border: none;
padding: 5px 10px;
border-radius: 3px;
cursor: pointer;
margin-left: 5px;
}
Functionality
Add JavaScript to make the Todo App interactive (optional). You can add functionality to add tasks, mark tasks as completed, and delete tasks using JavaScript.
This example demonstrates a basic Todo App UI with an input field to add tasks, a button to add tasks, and a list to display tasks. Each task has a delete button, and completed tasks are crossed out for visual indication.
Feel free to customize and enhance the Todo App UI according to your preferences and requirements. Happy coding!
Drill Down Props from Parent to Child in ReactJS
Introduction
In this project, we will create a simple React application to demonstrate the concept of passing props from a parent component to a child component, and then drilling down those props to even deeper child components. This is a fundamental concept in React and is essential for building scalable and reusable components.
Steps
Step 1: Create Parent and Child Components
Inside the src folder, create a new file named ParentComponent.js. Create a functional component named ParentComponent in ParentComponent.js. Create another file named ChildComponent.js. Create a functional component named ChildComponent in ChildComponent.js.
Step 3: Pass Props from Parent to Child
In ParentComponent.js, define some props (e.g., name, age). Render the ChildComponent inside ParentComponent and pass the props to it. In ChildComponent.js, receive the props and render them or pass them down further to deeper child components if needed.
Step 3: Display Props in Child Component
In ChildComponent.js, receive the props passed from the parent component. Display the received props in the JSX of the ChildComponent.
Example Code:
ParentComponent.js:
import React from 'react';
import ChildComponent from './ChildComponent';
const ParentComponent = () => {
return (
<div>
<h1>Parent Component</h1>
<ChildComponent name="John" age={30} />
</div>
);
};
export default ParentComponent;
ChildComponent.js:
import React from 'react';
const ChildComponent = (props) => {
return (
<div>
<h2>Child Component</h2>
<p>Name: {props.name}</p>
<p>Age: {props.age}</p>
</div>
);
};
export default ChildComponent;
App.js (Main Component):
import React from 'react';
import ParentComponent from './ParentComponent';
const App = () => {
return (
<div className="App">
<ParentComponent />
</div>
);
};
export default App;
Future Additions
- Nested Child Components: Add more levels of child components to demonstrate deeper drilling of props.
- Dynamic Props: Pass dynamic props from parent to child components based on user input or state changes.
- Event Handling: Pass down event handler functions as props to child components.
- Context API: Replace props drilling with React Context API for managing global state.
- Component Composition: Use component composition techniques to compose complex UI components from smaller, reusable components.
Fetch Data using an API in ReactJS
Introduction
In this project, we will create a simple React application to demonstrate how to fetch data from an API and display it on the webpage. We'll use the fetch API or Axios library to make HTTP requests to a public API, and then render the fetched data in our React components.
Project Overview
We'll build a React application that fetches and displays data from a public API. We'll use functional components and React hooks to manage state and lifecycle methods.
Step 1: Create Components
Inside the src folder, create a new file named UserList.js. Create a functional component named UserList in UserList.js. This component will be responsible for fetching and displaying the list of users from the API.
Step 2: Fetch Data from API
Use the fetch API or Axios library to make an HTTP GET request to a public API (e.g., JSONPlaceholder). Retrieve the list of users from the API response and store it in the component's state using React hooks (e.g., useState).
Step 3: Display Data in Component
Render the list of users fetched from the API in the UserList component. Use JSX to map through the list of users and display each user's information (e.g., name, email) in the UI.
Example Code:
UserList.js:
import React, { useState, useEffect } from 'react';
const UserList = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((data) => setUsers(data))
.catch((error) => console.error('Error fetching users:', error));
}, []);
return (
<div>
<h1>User List</h1>
<ul>
{users.map((user) => (
<li key={user.id}>
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
</li>
))}
</ul>
</div>
);
};
export default UserList;
App.js (Main Component):
import React from 'react';
import UserList from './UserList';
const App = () => {
return (
<div className="App">
<UserList />
</div>
);
};
export default App;
Future Additions
- Loading Spinner: Add a loading spinner while data is being fetched from the API.
- Error Handling: Implement error handling to display a friendly message if the API request fails.
- Pagination: Add pagination to handle large datasets and improve performance.
- Search Functionality: Implement a search bar to filter users based on criteria.
- Sorting: Allow users to sort the user list based on different attributes (e.g., name, email). Caching: Implement caching to avoid unnecessary API calls and improve performance.