Skip to content

Component Name: forgotPassword

Last Updated: 2025-10-22 Source Code: https://github.com/AANP-IT/I2C.Salesforce.Metadata/tree/STAGING/force-app/main/default/lwc/forgotPassword

API Name: c-forgotPassword Type: Form Component Target: lightningCommunity__Page, lightningCommunity__Default

Business Purpose

The forgotPassword component provides the initial step in AANP's password recovery workflow, allowing users to request password reset emails. It includes special handling for account lockout scenarios and integrates with the broader authentication security system to provide seamless password recovery experiences.

User Interface

Visual Description

  • Layout: Single-column centered form layout with Bootstrap grid system (col-12 col-md-6 col-lg-5)
  • Key UI Elements:
  • Page title "Reset Your Password" (centered, normal weight)
  • Email input field with validation
  • Submit button with loading state ("Reset Password" / "Loading...")
  • Success confirmation card (shown after submission)
  • Account lockout warning banner (shown when redirected from login)
  • Support callout with phone number and link to help center
  • Terms of use and privacy policy footer
  • Responsive:
  • Mobile (col-12): Full width on small screens
  • Tablet (col-md-6): 50% width on medium screens
  • Desktop (col-lg-5): ~42% width on large screens
  • All cards have consistent shadow and padding (p-7)

Screenshots

  • Desktop view: Centered card with email input, surrounded by support information and legal footer
  • Mobile view: Full-width stack maintaining readability
  • Success state: Confirmation message with user's email and next steps
  • Lockout state: Red danger alert textarea displaying lockout message

Component Structure

Files

  • forgotPassword.html - Template/markup
  • forgotPassword.js - JavaScript controller
  • forgotPassword.css - Custom styling
  • forgotPassword.js-meta.xml - Metadata configuration

HTML Template Structure

<template>
  <section class="wrapper">
    <div class="container">
      <form class="row justify-content-center">
        <div class="col-12 col-md-6 col-lg-5">
          <h2>Reset Your Password</h2>

          <!-- Success State -->
          <div lwc:if={isSend} class="card">
            <!-- Confirmation message with email -->
          </div>

          <!-- Form State -->
          <div lwc:else class="card">
            <!-- Lockout warning (conditional) -->
            <template if:true={showErrorMessage}>
              <textarea readonly class="alert-danger">...</textarea>
            </template>

            <!-- Email input -->
            <c-form-input type="email" />

            <!-- Submit button -->
            <button disabled={isLoading}>...</button>
          </div>

          <!-- Support callout -->
          <div class="card support">...</div>

          <!-- Terms and privacy footer -->
          <div class="text-center terms">...</div>
        </div>
      </form>
    </div>
  </section>
</template>

Key Template Features: - Conditional rendering with lwc:if={isSend} for success/form state toggle - Conditional lockout warning with if:true={showErrorMessage} - Custom child component c-form-input for email validation - Bootstrap classes for responsive grid layout - Disabled state on submit button during loading

JavaScript Controller

Properties (API)

No public @api properties - this is a standalone form component used on community pages.


Tracked Properties

@track isLoading

  • Type: Boolean
  • Purpose: Controls loading state during form submission
  • Updated When: Set to true on form submit, false after Apex call completes

@track errors

  • Type: Object
  • Purpose: Stores validation errors (currently unused in favor of c-form-input error handling)
  • Updated When: Not actively used in current implementation

@track showErrorMessage

  • Type: Boolean
  • Purpose: Controls display of account lockout warning message
  • Updated When: Set in connectedCallback() based on localStorage flag 'tooManyAttempts'

Non-Tracked Properties

email

  • Type: String
  • Default: Empty string
  • Purpose: Stores user's email address input
  • Updated When: User types in email field via handleInput()

loginUrl

  • Type: String
  • Default: basePath + "/login"
  • Purpose: URL for "Return to Login" navigation
  • Source: Constructed from @salesforce/community/basePath

isSend

  • Type: Boolean
  • Default: false
  • Purpose: Controls display of success confirmation message
  • Updated When: Set to true after successful password reset request

errorMessaged

  • Type: String
  • Default: 'Your account has been locked out. You can reset your password to unlock your account.'
  • Purpose: Lockout warning message text
  • Note: Contains typo in variable name ("errorMessaged" instead of "errorMessage")

Wire Adapters

None - component uses imperative Apex calls.


Public Methods

None - component has no @api methods.


Event Handlers

handleInput(event)

handleInput(event) {
  this.email = event.detail.value;
  this.validateEmail();
}

Triggered By: User typing in email input field (c-form-input component) Event Type: Custom event 'inputchange' from c-form-input Event Detail: { value: string } - current email value Action: Updates email property and triggers validation


handleFormSubmit(event)

async handleFormSubmit(event) {
  event.preventDefault();
  this.isLoading = true;
  const isValid = await this.validateEmail();
  // ... submission logic
  this.isLoading = false;
}

Triggered By: Click on "Reset Password" submit button Event Type: Click event Event Detail: Standard click event Action: 1. Prevents default form submission 2. Sets loading state 3. Validates email 4. Calls Apex method if valid 5. Shows success or error state 6. Clears loading state


Private Methods

validateEmail()

Purpose: Validates email format using c-form-input component's built-in validation Called By: handleInput(), handleFormSubmit() Returns: Boolean (true if valid, false if invalid) Implementation: Queries DOM for c-form-input component and calls its validateInput() method


clearLocalStorage()

Purpose: Removes 'tooManyAttempts' flag from localStorage after displaying lockout message Called By: connectedCallback() when lockout message is shown Side Effects: Modifies localStorage, logs to console


connectedCallback()

Purpose: Lifecycle hook that checks for lockout redirect and displays warning Called By: LWC framework on component initialization Implementation: - Uses setTimeout(0) to defer execution - Checks localStorage for 'tooManyAttempts' flag - Sets showErrorMessage if flag exists - Clears localStorage after displaying message


Events

Events Dispatched

None - this component does not dispatch custom events.


Events Handled

inputchange (from c-form-input)

Source: c-form-input child component Purpose: Capture email input changes Handler: handleInput(event)


Styling (CSS)

CSS Variables Used

None - component uses standard CSS properties.

Custom CSS Classes

  • .card-shadow: Box shadow for cards (0px 0px 11px -2px rgba(190, 190, 190, 0.64))
  • .terms: Footer text styling (#434343 color)
  • .terms a: Footer link styling (#0c3863 color)
  • .support: Support callout styling (italic, #0a0a0a)
  • .btn-submit: Primary button styling (#005999 background, white text, 50px height, 23px font)
  • .btn-submit:disabled: Disabled button state (#ccc background)
  • .btn-submit:hover: Hover state (#3072d7 background with underline)
  • .fs-xxs: Extra small font size (10px) for footer
  • label: Input label styling (13px font size)
  • .custom-link: Link styling for help center (#007bff with hover effects)

SLDS Classes

Component primarily uses Bootstrap classes from community template: - container, row, col-* - Grid layout - card - Card container - btn, btn-primary - Button styling - text-center, text-muted - Text utilities - alert, alert-danger - Alert styling (though using custom textarea implementation) - form-control - Form input styling - rounded-pill - Rounded button corners - bg-danger-subtle, border-danger - Danger state colors

Responsive Breakpoints

  • Mobile (<768px): col-12 - Full width form
  • Tablet (768-1024px): col-md-6 - 50% width form
  • Desktop (>1024px): col-lg-5 - ~42% width form, optimal reading width

Dependencies

Lightning Web Components (Base)

  • LightningElement - Base class
  • track decorator - For reactive properties

Custom LWC Components

  • c-form-input: Email input with built-in validation, error display, and methods (validateInput, clearError, setError)

Apex Classes

  • SelfRegisterController.forgotPassword(email): Initiates password reset process
  • Parameters: email (String)
  • Returns: Success/failure
  • Sends password reset email to user

Salesforce Objects & Fields

None directly - operates through Apex controller.

Static Resources

None

Labels

Hardcoded text (not using custom labels): - "Reset Your Password" - "We'll send a reset-password link to the email address associated with your account." - "Something went wrong, please try again later." - "Your account has been locked out. You can reset your password to unlock your account." - Support text and links

Community Services

  • @salesforce/community/basePath: Provides base URL for community navigation

Configuration

Component Meta XML

<targets>
    <target>lightningCommunity__Page</target>
    <target>lightningCommunity__Default</target>
</targets>

Available On: - Experience Builder pages (community/portal pages) - Default community page layouts

Design Properties

None - no configurable properties in App Builder.

User Interactions

Actions Available to Users

  1. Enter Email Address
  2. Trigger: Type in email input field
  3. Result: Real-time validation feedback, email stored in component state

  4. Submit Password Reset Request

  5. Trigger: Click "Reset Password" button
  6. Result:

    • Button shows "Loading..." state
    • Email validation occurs
    • Apex call sends reset email
    • Success message displayed with email confirmation
    • Or error message shown if failure
  7. Return to Login

  8. Trigger: Click "Return to Login" button (only visible after successful submission)
  9. Result: Navigate back to login page

  10. View Lockout Message

  11. Trigger: Automatic on page load if redirected from locked account
  12. Result: Red warning banner explains account is locked and can be unlocked via password reset

Validation & Error Handling

Client-Side Validation: - Email field: - Required field validation - Email format validation (via c-form-input component) - Real-time feedback on blur/change

Error Messages: - Invalid email format: Displayed inline below email field (via c-form-input) - Apex failure: "Something went wrong, please try again later." (inline below email field) - Account lockout: "Your account has been locked out. You can reset your password to unlock your account." (red banner above form)

Loading States: - Submit button shows "Loading..." text when isLoading is true - Button is disabled during loading to prevent duplicate submissions

Data Flow

Input Data Flow

User enters email
c-form-input oninputchange event
handleInput() captures event.detail.value
email property updated
validateEmail() called
c-form-input validates format

Output Data Flow

User clicks Reset Password
handleFormSubmit() validates email
forgotPassword Apex method called with email
Backend sends password reset email
Success: isSend = true, show confirmation
Error: Show error message in c-form-input

Lockout Detection Flow

Component loads (connectedCallback)
Check localStorage for 'tooManyAttempts'
If found: showErrorMessage = true
Display lockout warning banner
clearLocalStorage() removes flag

Performance Considerations

Render Optimization: - Uses conditional rendering (lwc:if/lwc:else) to show either form or success state - Minimal reactive properties reduce re-render cycles - Getter not needed due to simple property access

Data Volume: - Single email field, minimal data handling - No large datasets or complex computations

API Call Optimization: - Imperative Apex call (not @wire, so no caching) - Single call on form submission - No debouncing on validation (runs on every keystroke via handleInput) - Consideration: Email validation could benefit from debouncing to reduce DOM queries

Accessibility (a11y)

ARIA Labels: - Email input has proper label association (via c-form-input component) - No explicit ARIA attributes on buttons or alerts - Gap: Lockout warning textarea lacks proper ARIA role and live region

Keyboard Navigation: - Tab order: Natural DOM order (email field → submit button → links) - Enter key submits form (standard form behavior) - All interactive elements keyboard accessible - Gap: No keyboard shortcut for "Return to Login" action

Screen Reader Support: - Labels associated with inputs via c-form-input - Success/error state changes not announced dynamically - Gap: No aria-live regions for dynamic content changes - Gap: Loading state change not announced

Color Contrast: - Button colors (#005999, #3072d7) provide adequate contrast on white - Text colors (#434343, #0c3863) meet WCAG AA standards - Red danger alert background provides clear visual distinction - Passes WCAG AA: Likely yes, but needs formal audit

Testing

Jest Tests

Test File: Not present in repository Coverage: 0% - No tests found

Recommended Test Scenarios: - [ ] Component renders correctly with empty state - [ ] Email input captures user input - [ ] Email validation triggers on input change - [ ] Form submission prevented if email invalid - [ ] Apex method called with correct email parameter - [ ] Success state displays after successful submission - [ ] Error state displays after failed submission - [ ] Lockout message displays when localStorage flag present - [ ] LocalStorage flag cleared after lockout message shown - [ ] Return to Login navigation works correctly

Manual Testing Checklist

  • [ ] Desktop browser (Chrome, Firefox, Safari)
  • [ ] Mobile browser (iOS Safari, Android Chrome)
  • [ ] Tablet view (iPad, Android tablet)
  • [ ] Email validation works correctly
  • [ ] Password reset email received in inbox
  • [ ] Lockout scenario from login page
  • [ ] Support links work correctly
  • [ ] Terms and privacy links work
  • [ ] Button loading state functions properly
  • [ ] Form prevents double submission
  • [ ] Success message displays correctly

Usage Examples

In Experience Builder

  1. Drag "Forgot Password Form" component to forgot password page
  2. Component has no configuration properties
  3. Save and activate page
  4. Ensure page is accessible via /forgot-password route

In Parent Component

Not designed for embedding - standalone page component.

Programmatic Access

Not applicable - no public @api methods.

Changes & History

Current Implementation Notes: - Uses localStorage for lockout detection (client-side only) - Typo in property name: errorMessaged should be errorMessage - setTimeout(0) pattern for connectedCallback creates race condition risk - Email cleared on error, which may frustrate users who need to retype

⚠️ Pre-Go-Live Concerns

CRITICAL - Fix Before Go-Live

  • Race Condition: setTimeout(0) pattern for lockout detection creates timing vulnerabilities and is unreliable
  • Client-Side Security: Lockout detection relies entirely on localStorage manipulation, which users can bypass
  • Bypass Vulnerability: LocalStorage 'tooManyAttempts' flag can be easily manipulated or cleared by users
  • ARIA/Accessibility: Lockout warning textarea lacks proper alert role and aria-live region for screen reader announcement

HIGH - Address Soon After Go-Live

  • Error Handling: Catch block doesn't distinguish between different failure types (network, server, invalid email)
  • Form State: No loading state visualization during email validation (only on submission)
  • User Feedback: Clearing email field on error forces user to retype (frustrating UX)
  • Testing: No Jest tests present - component is untested
  • Hardcoded Text: All user-facing text hardcoded instead of using custom labels (i18n concern)

MEDIUM - Future Enhancement

  • Code Duplication: Email validation logic should be centralized across authentication components
  • Variable Naming: Fix typo in errorMessaged property name
  • Debouncing: Add debounce to email validation to reduce DOM queries on every keystroke
  • Error Messages: Externalize error messages to custom labels for easier maintenance
  • Component Communication: Consider using custom events instead of localStorage for cross-component communication
  • Async Handling: Standardize on async/await pattern (currently mixing promises and async)

LOW - Monitor

  • Console Logging: Debug statements present in production code (console.log in connectedCallback and clearLocalStorage)
  • Unused Properties: errors object is declared but never used
  • Form Reset: Consider preserving email on error instead of clearing
  • Success Metrics: Add analytics tracking for password reset success/failure rates

Maintenance Notes

Complexity: Low-Medium Recommended Review Schedule: Monthly review during authentication system maintenance

Key Maintainer Notes: - This component is the entry point for password recovery workflow - Lockout detection depends on localStorage flag set by loginForm component - Changes to this component should be coordinated with loginForm and resetPassword components - Email validation relies on c-form-input child component implementation - Apex controller SelfRegisterController.forgotPassword must remain compatible - Component uses Bootstrap/community template styling, not pure SLDS - Support contact information hardcoded in template (update if contact details change)

Browser Compatibility: - Chrome: 90+ - Firefox: 88+ - Safari: 14+ - Mobile: iOS 14+, Android 10+ - Uses modern JavaScript (async/await) - no IE11 support needed

Security Considerations: - Regular review of localStorage security dependencies - Monitor for abuse of password reset functionality - Consider rate limiting at Apex level - Ensure email delivery service is monitored - Review lockout detection mechanism with security team