diff --git a/7-bank-project/1-template-route/README.md b/7-bank-project/1-template-route/README.md index 03d2992a..3c344afd 100644 --- a/7-bank-project/1-template-route/README.md +++ b/7-bank-project/1-template-route/README.md @@ -1,14 +1,28 @@ # Build a Banking App Part 1: HTML Templates and Routes in a Web App -## Pre-Lecture Quiz +Modern web applications have revolutionized how we interact with digital services, from social media platforms to online banking systems. Unlike traditional websites that reload entire pages for each interaction, today's web apps provide seamless, app-like experiences that respond instantly to user actions. This smooth interaction is powered by sophisticated techniques that update only specific parts of the page, creating the fluid experience users expect. -[Pre-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/41) +| Traditional Multi-Page Apps | Modern Single-Page Apps | +|----------------------------|-------------------------| +| **Navigation** | Full page reload for each screen | Instant content switching | +| **Performance** | Slower due to complete HTML downloads | Faster with partial updates | +| **User Experience** | Jarring page flashes | Smooth, app-like transitions | +| **Data Sharing** | Difficult between pages | Easy state management | +| **Development** | Multiple HTML files to maintain | Single HTML with dynamic templates | + +**Understanding the evolution:** +- **Traditional apps** require server requests for every navigation action +- **Modern SPAs** load once and update content dynamically using JavaScript +- **User expectations** now favor instant, seamless interactions +- **Performance benefits** include reduced bandwidth and faster responses -### Introduction +In this lesson, you'll discover how to build the foundation of a single-page application (SPA) by creating a banking app with multiple screens that never require a full page reload. You'll learn how HTML templates work as reusable building blocks, how JavaScript routing enables navigation between different views, and how the browser's history API creates a natural browsing experience. These concepts form the backbone of modern web development and are used by popular frameworks like React, Vue, and Angular. -Since the advent of JavaScript in browsers, websites are becoming more interactive and complex than ever. Web technologies are now commonly used to create fully functional applications that runs directly into a browser that we call [web applications](https://en.wikipedia.org/wiki/Web_application). As Web apps are highly interactive, users do not want to wait for a full page reload every time an action is performed. That's why JavaScript is used to update the HTML directly using the DOM, to provide a smoother user experience. +By the end of this lesson, you'll have built a functional multi-screen banking application that demonstrates professional web development techniques. You'll understand how to create smooth user experiences that rival native mobile apps, setting the foundation for more advanced web development skills. Let's start building something amazing! + +## Pre-Lecture Quiz -In this lesson, we're going to lay out the foundations to create bank web app, using HTML templates to create multiple screens that can be displayed and updated without having to reload the entire HTML page. +[Pre-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/41) ### Prerequisite @@ -32,9 +46,35 @@ On your computer, create a folder named `bank` with a file named `index.html` in ``` +**Here's what this boilerplate provides:** +- **Establishes** the HTML5 document structure with proper DOCTYPE declaration +- **Configures** character encoding as UTF-8 for international text support +- **Enables** responsive design with the viewport meta tag for mobile compatibility +- **Sets** a descriptive title that appears in the browser tab +- **Creates** a clean body section where we'll build our application + +> πŸ“ **Project Structure Preview** +> +> **By the end of this lesson, your project will contain:** +> ``` +> bank/ +> β”œβ”€β”€ index.html +> β”œβ”€β”€ app.js +> └── style.css +> ``` +> +> **File responsibilities:** +> - **index.html**: Contains all templates and provides the app structure +> - **app.js**: Handles routing, navigation, and template management +> - **Templates**: Define the UI for login, dashboard, and other screens + --- -## HTML templates +## HTML Templates + +HTML templates are one of the most powerful features for building dynamic web applications. Instead of creating separate HTML files for each screen in your app, templates allow you to define reusable HTML structures that can be dynamically loaded and displayed as needed. This approach significantly improves performance and provides a smoother user experience. + +Think of templates as blueprints for different parts of your application. Just like an architect uses blueprints to construct different rooms in a building, you'll use HTML templates to construct different screens in your web app. The browser doesn't display these templates initially – they remain hidden until your JavaScript code activates them. If you want to create multiple screens for a web page, one solution would be to create one HTML file for every screen you want to display. However, this solution comes with some inconvenience: @@ -51,9 +91,13 @@ We'll create a bank app with two screens: the login page and the dashboard. Firs
Loading...
``` -We're giving it an `id` to make it easier to locate it with JavaScript later. +**Understanding this placeholder:** +- **Creates** a container with the ID "app" where all screens will be displayed +- **Shows** a loading message until the JavaScript initializes the first screen +- **Provides** a single mounting point for our dynamic content +- **Enables** easy targeting from JavaScript using `document.getElementById()` -> Tip: since the content of this element will be replaced, we can put in a loading message or indicator that will be shown while the app is loading. +> πŸ’‘ **Pro Tip**: Since the content of this element will be replaced, we can put in a loading message or indicator that will be shown while the app is loading. Next, let's add below the HTML template for the login page. For now we'll only put in there a title and a section containing a link that we'll use to perform the navigation. @@ -66,6 +110,12 @@ Next, let's add below the HTML template for the login page. For now we'll only p ``` +**Breaking down this login template:** +- **Defines** a template with the unique identifier "login" for JavaScript targeting +- **Includes** a main heading that establishes the app's branding +- **Contains** a semantic `
` element to group related content +- **Provides** a navigation link that will route users to the dashboard + Then we'll add another HTML template for the dashboard page. This page will contain different sections: - A header with a title and a logout link @@ -97,11 +147,24 @@ Then we'll add another HTML template for the dashboard page. This page will cont ``` -> Tip: when creating HTML templates, if you want to see what it will look like, you can comment out the `` lines by enclosing them with ``. +**Let's understand each part of this dashboard:** +- **Structures** the page with a semantic `
` element containing navigation +- **Displays** the app title consistently across screens for branding +- **Provides** a logout link that routes back to the login screen +- **Shows** the current account balance in a dedicated section +- **Organizes** transaction data using a properly structured HTML table +- **Defines** table headers for Date, Object, and Amount columns +- **Leaves** the table body empty for dynamic content injection later + +> πŸ’‘ **Pro Tip**: When creating HTML templates, if you want to see what it will look like, you can comment out the `` lines by enclosing them with ``. βœ… Why do you think we use `id` attributes on the templates? Could we use something else like classes? -## Displaying templates with JavaScript +## Displaying Templates with JavaScript + +Now that we have our HTML templates defined, we need to bring them to life with JavaScript. Templates by themselves are invisible – they're like blueprints waiting to be built into actual structures. JavaScript provides the tools to select a template, create a working copy of it, and insert it into the visible part of your webpage. + +The process of displaying a template involves three essential steps that work together to transform hidden template code into visible, interactive content. Understanding this process is crucial because it's the foundation of how modern web frameworks manage dynamic content. If you try your current HTML file in a browser, you'll see that it gets stuck displaying `Loading...`. That's because we need to add some JavaScript code to instantiate and display the HTML templates. @@ -111,6 +174,29 @@ Instantiating a template is usually done in 3 steps: 2. Clone the template element, using [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode). 3. Attach it to the DOM under a visible element, for example using [`appendChild`](https://developer.mozilla.org/docs/Web/API/Node/appendChild). +```mermaid +flowchart TD + A[πŸ” Step 1: Find Template] --> B[πŸ“‹ Step 2: Clone Template] + B --> C[πŸ”— Step 3: Attach to DOM] + + A1["document.getElementById('login')"] --> A + B1["template.content.cloneNode(true)"] --> B + C1["app.appendChild(view)"] --> C + + C --> D[πŸ‘οΈ Template Visible to User] + + style A fill:#e1f5fe + style B fill:#f3e5f5 + style C fill:#e8f5e8 + style D fill:#fff3e0 +``` + +**Visual breakdown of the process:** +- **Step 1** locates the hidden template in the DOM structure +- **Step 2** creates a working copy that can be safely modified +- **Step 3** inserts the copy into the visible page area +- **Result** is a functional screen that users can interact with + βœ… Why do we need to clone the template before attaching it to the DOM? What do you think would happen if we skipped this step? ### Task @@ -121,6 +207,12 @@ Create a new file named `app.js` in your project folder and import that file in ``` +**Understanding this script import:** +- **Links** the JavaScript file to our HTML document +- **Uses** the `defer` attribute to ensure the script runs after HTML parsing completes +- **Enables** access to all DOM elements since they're fully loaded before script execution +- **Follows** modern best practices for script loading and performance + Now in `app.js`, we'll create a new function `updateRoute`: ```js @@ -133,7 +225,12 @@ function updateRoute(templateId) { } ``` -What we do here is exactly the 3 steps described above. We instantiate the template with the id `templateId`, and put its cloned content within our app placeholder. Note that we need to use `cloneNode(true)` to copy the entire subtree of the template. +**Step by step, here's what's happening:** +- **Locates** the template element using its unique ID +- **Creates** a deep copy of the template's content using `cloneNode(true)` +- **Finds** the app container where the content will be displayed +- **Clears** any existing content from the app container +- **Inserts** the cloned template content into the visible DOM Now call this function with one of the template and look at the result. @@ -141,9 +238,41 @@ Now call this function with one of the template and look at the result. updateRoute('login'); ``` +**What this function call accomplishes:** +- **Activates** the login template by passing its ID as a parameter +- **Demonstrates** how to programmatically switch between different app screens +- **Shows** the login screen in place of the "Loading..." message + βœ… What's the purpose of this code `app.innerHTML = '';`? What happens without it? -## Creating routes +## Creating Routes + +Routing is the backbone of modern web applications – it's what makes your app feel like a cohesive experience rather than a collection of disconnected pages. When you navigate through a professional web app like Gmail or Twitter, the URL changes to reflect where you are, but the page doesn't reload. This seamless experience is powered by client-side routing, which maps URLs to specific content or views. + +In traditional multi-page websites, the web server handles routing automatically by serving different HTML files based on the URL path. However, in single-page applications (SPAs), we need to implement this routing logic ourselves using JavaScript. This gives us complete control over how navigation works and enables the smooth, app-like experience users expect. + +```mermaid +flowchart LR + A["🌐 URL Path
/dashboard"] --> B["πŸ—ΊοΈ Routes Object
Lookup"] + B --> C["🎯 Template ID
'dashboard'"] + C --> D["πŸ“„ Find Template
getElementById"] + D --> E["πŸ‘οΈ Display Screen
Clone & Append"] + + F["πŸ“ /login"] --> G["🎯 'login'"] + H["πŸ“ /unknown"] --> I["❌ Not Found"] + I --> J["πŸ”„ Redirect to /login"] + + style B fill:#e3f2fd + style E fill:#e8f5e8 + style I fill:#ffebee + style J fill:#fff3e0 +``` + +**Understanding the routing flow:** +- **URL changes** trigger a lookup in our routes configuration +- **Valid routes** map to specific template IDs for rendering +- **Invalid routes** trigger fallback behavior to prevent broken states +- **Template rendering** follows the three-step process we learned earlier When talking about a web app, we call *Routing* the intent to map **URLs** to specific screens that should be displayed. On a website with multiple HTML files, this is done automatically as the file paths are reflected on the URL. For example, with these files in your project folder: @@ -174,6 +303,12 @@ const routes = { }; ``` +**Understanding this routes configuration:** +- **Defines** a mapping between URL paths and template identifiers +- **Uses** object syntax where keys are URL paths and values contain template information +- **Enables** easy lookup of which template to display for any given URL +- **Provides** a scalable structure for adding new routes in the future + Now let's modify a bit the `updateRoute` function. Instead of passing directly the `templateId` as an argument, we want to retrieve it by first looking at the current URL, and then use our map to get the corresponding template ID value. We can use [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname) to get only the path section from the URL. ```js @@ -189,11 +324,36 @@ function updateRoute() { } ``` +**Breaking down what happens here:** +- **Extracts** the current path from the browser's URL using `window.location.pathname` +- **Looks up** the corresponding route configuration in our routes object +- **Retrieves** the template ID from the route configuration +- **Follows** the same template rendering process as before +- **Creates** a dynamic system that responds to URL changes + Here we mapped the routes we declared to the corresponding template. You can try it that it works correctly by changing the URL manually in your browser. βœ… What happens if you enter an unknown path in the URL? How could we solve this? -## Adding navigation +## Adding Navigation + +Great routing logic is only half the equation – we also need intuitive navigation that allows users to move between screens effortlessly. In traditional websites, clicking a link causes the entire page to reload, which breaks the smooth experience we're trying to create. Instead, we'll implement programmatic navigation that updates the URL and content seamlessly. + +Effective navigation in a single-page application requires coordinating two essential actions: updating the browser's URL to reflect the current screen, and displaying the appropriate content. This coordination ensures that users can bookmark specific screens, use the browser's back button, and share URLs that work exactly as expected. + +> πŸ—οΈ **Architecture Insight**: Navigation System Components +> +> **What you're building:** +> - **πŸ”„ URL Management**: Updates browser address bar without page reloads +> - **πŸ“‹ Template System**: Swaps content dynamically based on current route +> - **πŸ“š History Integration**: Maintains browser back/forward button functionality +> - **πŸ›‘οΈ Error Handling**: Graceful fallbacks for invalid or missing routes +> +> **How components work together:** +> - **Listens** for navigation events (clicks, history changes) +> - **Updates** the URL using the History API +> - **Renders** the appropriate template for the new route +> - **Maintains** a seamless user experience throughout The next step for our app is to add the possibility to navigate between pages without having to change the URL manually. This implies two things: @@ -204,7 +364,7 @@ We already took care of the second part with the `updateRoute` function, so we h We'll have to use JavaScript and more specifically the [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState) that allows to update the URL and create a new entry in the browsing history, without reloading the HTML. -> Note: While the HTML anchor element [``](https://developer.mozilla.org/docs/Web/HTML/Element/a) can be used on its own to create hyperlinks to different URLs, it will make the browser reload the HTML by default. It is necessary to prevent this behavior when handling routing with custom javascript, using the preventDefault() function on the click event. +> ⚠️ **Important Note**: While the HTML anchor element [``](https://developer.mozilla.org/docs/Web/HTML/Element/a) can be used on its own to create hyperlinks to different URLs, it will make the browser reload the HTML by default. It is necessary to prevent this behavior when handling routing with custom javascript, using the preventDefault() function on the click event. ### Task @@ -217,6 +377,12 @@ function navigate(path) { } ``` +**Understanding this navigation function:** +- **Updates** the browser's URL to the new path using `history.pushState` +- **Adds** a new entry to the browser's history stack for proper back/forward button support +- **Triggers** the `updateRoute()` function to display the corresponding template +- **Maintains** the single-page app experience without page reloads + This method first updates the current URL based on the path given, then updates the template. The property `window.location.origin` returns the URL root, allowing us to reconstruct a complete URL from a given path. Now that we have this function, we can take care of the problem we have if a path does not match any defined route. We'll modify the `updateRoute` function by adding a fallback to one of the existing route if we can't find a match. @@ -230,9 +396,20 @@ function updateRoute() { return navigate('/login'); } - ... + const template = document.getElementById(route.templateId); + const view = template.content.cloneNode(true); + const app = document.getElementById('app'); + app.innerHTML = ''; + app.appendChild(view); +} ``` +**Key points to remember:** +- **Checks** if a route exists for the current path +- **Redirects** to the login page when an invalid route is accessed +- **Provides** a fallback mechanism that prevents broken navigation +- **Ensures** users always see a valid screen, even with incorrect URLs + If a route cannot be found, we'll now redirect to the `login` page. Now let's create a function to get the URL when a link is clicked, and to prevent the browser's default link behavior: @@ -244,7 +421,11 @@ function onLinkClick(event) { } ``` -Let's complete the navigation system by adding bindings to our *Login* and *Logout* links in the HTML. +**Breaking down this click handler:** +- **Prevents** the browser's default link behavior using `preventDefault()` +- **Extracts** the destination URL from the clicked link element +- **Calls** our custom navigate function instead of reloading the page +- **Maintains** the smooth single-page application experience ```html Login @@ -252,15 +433,60 @@ Let's complete the navigation system by adding bindings to our *Login* and *Logo Logout ``` -The `event` object above, captures the `click` event and passes it to our `onLinkClick` function. +**What this onclick binding accomplishes:** +- **Connects** each link to our custom navigation system +- **Passes** the click event to our `onLinkClick` function for processing +- **Enables** smooth navigation without page reloads +- **Maintains** proper URL structure that users can bookmark or share -Using the [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) attribute bind the `click` event to JavaScript code, here the call to the `navigate()` function. +The [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) attribute bind the `click` event to JavaScript code, here the call to the `navigate()` function. Try clicking on these links, you should be now able to navigate between the different screens of your app. βœ… The `history.pushState` method is part of the HTML5 standard and implemented in [all modern browsers](https://caniuse.com/?search=pushState). If you're building a web app for older browsers, there's a trick you can use in place of this API: using a [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment) before the path you can implement routing that works with regular anchor navigation and does not reload the page, as it's purpose was to create internal links within a page. -## Handling the browser's back and forward buttons +## Handling the Browser's Back and Forward Buttons + +Users expect web applications to behave like traditional websites when it comes to browser navigation. When someone clicks the back button, they should return to the previous screen, and the forward button should work just as intuitively. However, single-page applications need special handling to make this work correctly. + +The browser's navigation buttons interact with the history stack that we've been building with `history.pushState`. Each time we navigate to a new screen, we add an entry to this stack. When users click back or forward, the browser moves through this stack, but our application needs to respond to these changes and update the displayed content accordingly. + +```mermaid +sequenceDiagram + participant User + participant Browser + participant App + participant Template + + User->>Browser: Clicks "Login" link + Browser->>App: onclick event triggered + App->>App: preventDefault() & navigate('/dashboard') + App->>Browser: history.pushState('/dashboard') + Browser->>Browser: URL updates to /dashboard + App->>App: updateRoute() called + App->>Template: Find & clone dashboard template + Template->>App: Return cloned content + App->>Browser: Replace app content with template + Browser->>User: Display dashboard screen + + Note over User,Template: User clicks browser back button + + User->>Browser: Clicks back button + Browser->>Browser: History moves back to /login + Browser->>App: popstate event fired + App->>App: updateRoute() called automatically + App->>Template: Find & clone login template + Template->>App: Return cloned content + App->>Browser: Replace app content with template + Browser->>User: Display login screen +``` + +**Key interaction points:** +- **User actions** trigger navigation through clicks or browser buttons +- **App intercepts** link clicks to prevent page reloads +- **History API** manages URL changes and browser history stack +- **Templates** provide the content structure for each screen +- **Event listeners** ensure the app responds to all navigation types Using the `history.pushState` creates new entries in the browser's navigation history. You can check that by holding the *back button* of your browser, it should display something like this: @@ -279,7 +505,14 @@ window.onpopstate = () => updateRoute(); updateRoute(); ``` -> Note: we used an [arrow function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) here to declare our `popstate` event handler for conciseness, but a regular function would work the same. +**Understanding this history integration:** +- **Listens** for `popstate` events that occur when users navigate with browser buttons +- **Uses** an arrow function for concise event handler syntax +- **Calls** `updateRoute()` automatically whenever the history state changes +- **Initializes** the app by calling `updateRoute()` when the page first loads +- **Ensures** the correct template displays regardless of how users navigate + +> πŸ’‘ **Pro Tip**: We used an [arrow function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) here to declare our `popstate` event handler for conciseness, but a regular function would work the same. Here's a refresher video on arrow functions: @@ -303,6 +536,12 @@ Use the Agent mode to complete the following challenge: Add a new template and route for a third page that shows the credits for this app. +**Challenge goals:** +- **Create** a new HTML template with appropriate content structure +- **Add** the new route to your routes configuration object +- **Include** navigation links to and from the credits page +- **Test** that all navigation works correctly with browser history + ## Post-Lecture Quiz [Post-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/42) @@ -311,6 +550,12 @@ Add a new template and route for a third page that shows the credits for this ap Routing is one of the surprisingly tricky parts of web development, especially as the web moves from page refresh behaviors to Single Page Application page refreshes. Read a little about [how the Azure Static Web App service](https://docs.microsoft.com/azure/static-web-apps/routes/?WT.mc_id=academic-77807-sagibbon) handles routing. Can you explain why some of the decisions described on that document are necessary? +**Additional learning resources:** +- **Explore** how popular frameworks like React Router and Vue Router implement client-side routing +- **Research** the differences between hash-based routing and history API routing +- **Learn** about server-side rendering (SSR) and how it affects routing strategies +- **Investigate** how Progressive Web Apps (PWAs) handle routing and navigation + ## Assignment [Improve the routing](assignment.md) diff --git a/7-bank-project/1-template-route/assignment.md b/7-bank-project/1-template-route/assignment.md index e93ad147..084ca911 100644 --- a/7-bank-project/1-template-route/assignment.md +++ b/7-bank-project/1-template-route/assignment.md @@ -1,11 +1,41 @@ -# Improve the routing +# Improve the Routing ## Instructions +Now that you've built a basic routing system, it's time to enhance it with professional features that improve user experience and provide better developer tools. Real-world applications need more than just template switching \u2013 they require dynamic page titles, lifecycle hooks, and extensible architectures. + +In this assignment, you'll extend your routing implementation with two essential features that are commonly found in production web applications. These enhancements will make your banking app feel more polished and provide a foundation for future functionality. + The routes declaration contains currently only the template ID to use. But when displaying a new page, a bit more is needed sometimes. Let's improve our routing implementation with two additional features: -- Give titles to each template and update the window title with this new title when the template changes. -- Add an option to run some code after the template changes. We want to print `'Dashboard is shown'` in the developer console every time the dashboard page is displayed. +### Feature 1: Dynamic Page Titles +**Objective:** Give titles to each template and update the window title with this new title when the template changes. + +**Why this matters:** +- **Improves** user experience by showing descriptive browser tab titles +- **Enhances** accessibility for screen readers and assistive technologies +- **Provides** better bookmarking and browser history context +- **Follows** professional web development best practices + +**Implementation approach:** +- **Extend** the routes object to include title information for each route +- **Modify** the `updateRoute()` function to update `document.title` dynamically +- **Test** that titles change correctly when navigating between screens + +### Feature 2: Route Lifecycle Hooks +**Objective:** Add an option to run some code after the template changes. We want to print `'Dashboard is shown'` in the developer console every time the dashboard page is displayed. + +**Why this matters:** +- **Enables** custom logic execution when specific routes load +- **Provides** hooks for analytics, logging, or initialization code +- **Creates** a foundation for more complex route behaviors +- **Demonstrates** the observer pattern in web development + +**Implementation approach:** +- **Add** an optional callback function property to route configurations +- **Execute** the callback function (if present) after template rendering completes +- **Ensure** the feature works for any route with a defined callback +- **Test** that the console message appears when visiting the dashboard ## Rubric diff --git a/7-bank-project/2-forms/README.md b/7-bank-project/2-forms/README.md index 9183e5d5..db6acc81 100644 --- a/7-bank-project/2-forms/README.md +++ b/7-bank-project/2-forms/README.md @@ -4,279 +4,731 @@ [Pre-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/43) -### Introduction +Forms are the gateway between users and your web application. They're how users share their information, create accounts, and interact with your app's features. Think of forms as the digital equivalent of paperwork – they collect essential information, but unlike traditional paperwork, web forms can provide instant feedback, validate data in real-time, and create seamless user experiences. -In almost all modern web apps, you can create an account to have your own private space. As multiple users can access a web app at the same time, you need a mechanism to store each user personal data separately and select which information to display information. We won't cover how to manage [user identity securely](https://en.wikipedia.org/wiki/Authentication) as it's an extensive topic on its own, but we'll make sure each user is able to create one (or more) bank account on our app. +In this lesson, you'll transform your static banking app into an interactive application where users can register for accounts and log in securely. You'll discover how to build robust forms using modern HTML5 features, handle user input with JavaScript, and communicate with a server API to store and retrieve user data. These skills form the foundation of user authentication and data management in web development. -In this part we'll use HTML forms to add login and registration to our web app. We'll see how to send the data to a server API programmatically, and ultimately how to define basic validation rules for user inputs. +By the end of this lesson, you'll have created a complete user registration and login system, complete with form validation and server communication. You'll understand how forms work behind the scenes and be equipped to build secure, user-friendly input systems for any web application. Let's dive in and bring your banking app to life! -### Prerequisite +## Prerequisites -You need to have completed the [HTML templates and routing](../1-template-route/README.md) of the web app for this lesson. You also need to install [Node.js](https://nodejs.org) and [run the server API](../api/README.md) locally so you can send data to create accounts. +Before diving into form development, let's ensure your development environment is properly configured. This lesson builds directly on the foundation you created in the previous session, so having everything set up correctly is crucial for success. -**Take note** -You will have two terminals running at the same time as listed below. -1. For the main bank app we built in the [HTML templates and routing](../1-template-route/README.md) lesson -2. For the [Bank APP server API](../api/README.md) we just setup above. +### Required Setup -You need two of the servers up and running to follow through with the rest of the lesson. They are listening on different ports(port `3000` and port `5000`) so everything should work just fine. +| Component | Status | Description | +|-----------|--------|-------------| +| [HTML Templates](../1-template-route/README.md) | βœ… Required | Your basic banking app structure | +| [Node.js](https://nodejs.org) | βœ… Required | JavaScript runtime for the server | +| [Bank API Server](../api/README.md) | βœ… Required | Backend service for data storage | -You can test that the server is running properly by executing this command in a terminal: +> πŸ’‘ **Development Tip**: You'll be running two separate servers simultaneously – one for your front-end banking app and another for the backend API. This setup mirrors real-world development where frontend and backend services operate independently. -```sh +### Server Configuration + +**Your development environment will include:** +- **Frontend server**: Serves your banking app (typically port `3000`) +- **Backend API server**: Handles data storage and retrieval (port `5000`) +- **Both servers** can run simultaneously without conflicts + +**Testing your API connection:** +```bash curl http://localhost:5000/api -# -> should return "Bank API v1.0.0" as a result +# Expected response: "Bank API v1.0.0" ``` +**If you see the API version response, you're ready to proceed!** + --- -## Form and controls +## Understanding HTML Forms and Controls + +HTML forms are the primary way users interact with web applications. They provide a structured way to collect, validate, and submit user data. Think of forms as digital contracts – they define what information you need and how users can provide it safely and efficiently. + +Modern forms go far beyond simple text boxes. They include specialized input types, built-in validation, and accessibility features that create better user experiences while maintaining security and data integrity. -The `
` element encapsulates a section of an HTML document where the user can input and submit data with interactive controls. There are all sorts of user interface (UI) controls that can be used within a form, the most common one being the `` and the ` +
``` -The `name` attribute will be used as the property name when the form data will be sent over. The `id` attribute is used to associate a `