🎯 Self-Contained Form Demo (FastAPI)

This form includes ZERO external dependencies!

Current style: Bootstrap 5

Everything needed is embedded in the form HTML below:

Bootstrap Material
Your unique username (3-50 characters)
Your email address for account verification
Password must be at least 8 characters
Re-enter your password to confirm
Your age in years
Select your account type
Debug panel (development only)
<form id=""
      class="pydantic-form needs-validation"
      style=""
      method="POST"
      action="/self-contained?style=bootstrap"
      novalidate>
    
    <div class="mb-3"><label for="username"><i class="bi bi-person"></i> Username *</label>
<input name="username" id="username" class="form-control" value="alex_demo_user" required="required" minlength="3" maxlength="11" placeholder="Choose a username" pattern="\d{3}-\d{2}-\d{4}" inputmode="numeric" autocomplete="off" type="text" />
<div class="form-text">Your unique username (3-50 characters)</div></div>
<div class="mb-3"><label for="email"><i class="bi bi-envelope"></i> Email Address *</label>
<input name="email" id="email" class="form-control" value="alex.demo@example.com" required="required" placeholder="your.email@example.com" inputmode="email" type="email" />
<div class="form-text">Your email address for account verification</div></div>
<div class="mb-3"><label for="password"><i class="bi bi-lock"></i> Password *</label>
<input name="password" id="password" class="form-control" value="SecurePass123!" required="required" minlength="8" placeholder="Create a strong password" autocomplete="new-password" type="password" />
<div class="form-text">Password must be at least 8 characters</div></div>
<div class="mb-3"><label for="confirm_password"><i class="bi bi-lock"></i> Confirm Password *</label>
<input name="confirm_password" id="confirm_password" class="form-control" value="SecurePass123!" required="required" placeholder="Confirm your password" autocomplete="new-password" type="password" />
<div class="form-text">Re-enter your password to confirm</div></div>
<div class="mb-3"><label for="age"><i class="bi bi-calendar"></i> Age</label>
<input name="age" id="age" class="form-control" value="28" placeholder="Your age (optional)%" min="0" max="100" step="0.1" inputmode="numeric" type="number" />
<div class="form-text">Your age in years</div></div>
<div class="mb-3"><div class="mb-3">
<label for="role" class="form-label">Account Type</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-bi bi-shield"></i></span>
<select name="role" id="role" class="form-select"><option value="user" selected>👤 User</option>
<option value="admin">🔑 Admin</option>
<option value="moderator">🛡️ Moderator</option></select>
</div>
<div class="form-text">Select your account type</div>
</div></div>
    
<button type="submit" class="btn btn-primary">Submit</button>

</form>


<script>
(function() {
    document.addEventListener('DOMContentLoaded', function() {
        // Prevent Enter key from submitting forms unless on submit button
        const forms = document.querySelectorAll('form.pydantic-form');
        forms.forEach(function(form) {
            form.addEventListener('keydown', function(e) {
                // Check if Enter key is pressed
                if (e.key === 'Enter' || e.keyCode === 13) {
                    const target = e.target;

                    // Allow Enter in textareas (for multi-line input)
                    if (target.tagName === 'TEXTAREA') {
                        return;
                    }

                    // Allow Enter on submit buttons
                    if (target.tagName === 'BUTTON' && target.type === 'submit') {
                        return;
                    }

                    // Allow Enter on input type="submit"
                    if (target.tagName === 'INPUT' && target.type === 'submit') {
                        return;
                    }

                    // Prevent form submission for all other cases
                    e.preventDefault();
                    return false;
                }
            });
        });
    });
})();
</script>
class UserRegistrationForm(FormModel):
    """User registration form with username, email, and password."""

    username: str = FormField(
        title="Username",
        input_type="text",
        placeholder="Choose a username",
        help_text="Your unique username (3-50 characters)",
        icon="person",
        min_length=3,
        max_length=50
    )

    email: EmailStr = FormField(
        title="Email Address",
        input_type="email",
        placeholder="your.email@example.com",
        help_text="Your email address for account verification",
        icon="email"
    )

    password: str = FormField(
        title="Password",
        input_type="password",
        placeholder="Create a strong password",
        help_text="Password must be at least 8 characters",
        icon="lock",
        min_length=8
    )

    confirm_password: str = FormField(
        title="Confirm Password",
        input_type="password",
        placeholder="Confirm your password",
        help_text="Re-enter your password to confirm",
        icon="lock"
    )

    age: Optional[int] = FormField(
        None,
        title="Age",
        input_type="number",
        placeholder="Your age (optional)",
        help_text="Your age in years",
        icon="calendar",
        min_value=13,
        max_value=120
    )

    role: UserRole = FormField(
        UserRole.USER,
        title="Account Type",
        input_type="select",
        options=[
            {"value": "user", "label": "👤 User"},
            {"value": "admin", "label": "🔑 Admin"},
            {"value": "moderator", "label": "🛡️ Moderator"}
        ],
        help_text="Select your account type",
        icon="shield"
    )

    @field_validator("username")
    @classmethod
    def validate_username(cls, v):
        if not v.strip():
            raise ValueError("Username cannot be empty")
        if not v.replace('_', '').replace('-', '').isalnum():
            raise ValueError("Username can only contain letters, numbers, hyphens, and underscores")
        return v.strip()

    @field_validator("confirm_password")
    @classmethod
    def validate_passwords_match(cls, v, info):
        if 'password' in info.data and v != info.data['password']:
            raise ValueError("Passwords do not match")
        return v
{
  "$defs": {
    "UserRole": {
      "description": "User roles.",
      "enum": [
        "user",
        "admin",
        "moderator"
      ],
      "title": "UserRole",
      "type": "string"
    }
  },
  "description": "User registration form with username, email, and password.",
  "properties": {
    "username": {
      "autofocus": false,
      "description": "Your unique username (3-50 characters)",
      "disabled": false,
      "help_text": "Your unique username (3-50 characters)",
      "icon": "person",
      "input_type": "text",
      "maxLength": 50,
      "minLength": 3,
      "placeholder": "Choose a username",
      "readonly": false,
      "title": "Username",
      "type": "string"
    },
    "email": {
      "autofocus": false,
      "description": "Your email address for account verification",
      "disabled": false,
      "format": "email",
      "help_text": "Your email address for account verification",
      "icon": "email",
      "input_type": "email",
      "placeholder": "your.email@example.com",
      "readonly": false,
      "title": "Email Address",
      "type": "string"
    },
    "password": {
      "autofocus": false,
      "description": "Password must be at least 8 characters",
      "disabled": false,
      "help_text": "Password must be at least 8 characters",
      "icon": "lock",
      "input_type": "password",
      "minLength": 8,
      "placeholder": "Create a strong password",
      "readonly": false,
      "title": "Password",
      "type": "string"
    },
    "confirm_password": {
      "autofocus": false,
      "description": "Re-enter your password to confirm",
      "disabled": false,
      "help_text": "Re-enter your password to confirm",
      "icon": "lock",
      "input_type": "password",
      "placeholder": "Confirm your password",
      "readonly": false,
      "title": "Confirm Password",
      "type": "string"
    },
    "age": {
      "anyOf": [
        {
          "maximum": 120,
          "minimum": 13,
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "autofocus": false,
      "default": null,
      "description": "Your age in years",
      "disabled": false,
      "help_text": "Your age in years",
      "icon": "calendar",
      "input_type": "number",
      "placeholder": "Your age (optional)",
      "readonly": false,
      "title": "Age"
    },
    "role": {
      "$ref": "#/$defs/UserRole",
      "autofocus": false,
      "default": "user",
      "description": "Select your account type",
      "disabled": false,
      "help_text": "Select your account type",
      "icon": "shield",
      "input_type": "select",
      "options": [
        {
          "label": "\ud83d\udc64 User",
          "value": "user"
        },
        {
          "label": "\ud83d\udd11 Admin",
          "value": "admin"
        },
        {
          "label": "\ud83d\udee1\ufe0f Moderator",
          "value": "moderator"
        }
      ],
      "readonly": false,
      "title": "Account Type"
    }
  },
  "required": [
    "username",
    "email",
    "password",
    "confirm_password"
  ],
  "title": "UserRegistrationForm",
  "type": "object"
}
{
  "username": {
    "required": true,
    "type": "string",
    "minLength": 3,
    "maxLength": 50
  },
  "email": {
    "required": true,
    "type": "string",
    "format": "email"
  },
  "password": {
    "required": true,
    "type": "string",
    "minLength": 8
  },
  "confirm_password": {
    "required": true,
    "type": "string"
  },
  "age": {
    "required": false
  },
  "role": {
    "required": false
  }
}
{
  "errors": {},
  "data": {
    "username": "alex_demo_user",
    "email": "alex.demo@example.com",
    "password": "SecurePass123!",
    "confirm_password": "SecurePass123!",
    "age": 28,
    "role": "user"
  }
}

🔧 What's Included:

Template Usage: <div>{{ form_html | safe }}</div>

← Back to FastAPI Examples