📋 Bài 4: HTML Forms

Học cách tạo biểu mẫu để thu thập thông tin từ người dùng

📋 HTML Forms là gì?

💡 Định nghĩa

HTML Forms là cách để thu thập thông tin từ người dùng thông qua các input fields như text, email, password, checkbox, radio buttons, etc. Forms là cầu nối giữa frontend và backend.

📝

Form Container

Thẻ form chứa tất cả các input elements

<form> - Container chính
⌨️

Input Elements

Các loại input để người dùng nhập liệu

<input> <textarea> <select>
🏷️

Labels & Groups

Tổ chức và mô tả các form elements

<label> <fieldset> <legend>
🎯

Buttons

Submit, reset và các action buttons

<button> <input type="submit">

📝 Thẻ <form> - Container

🏗️ Cấu trúc cơ bản

Thẻ <form> là container chứa tất cả các input elements và định nghĩa cách dữ liệu được gửi đi.

Cấu trúc form cơ bản
<!-- Form cơ bản -->
<form action="/submit" method="POST">
    <!-- Các input elements ở đây -->
    <label for="name">Tên:</label>
    <input type="text" id="name" name="name" required>
    
    <button type="submit">Gửi</button>
</form>

<!-- Form với nhiều thuộc tính -->
<form 
    action="https://example.com/process-form" 
    method="POST"
    target="_blank"
    enctype="multipart/form-data"
    novalidate
    autocomplete="on"
>
    <!-- Form content -->
</form>

⚙️ Thuộc tính quan trọng của <form>

🎯

action

URL nơi form data được gửi đến

action="/submit-form"
action="mailto:admin@example.com"
📤

method

HTTP method để gửi data

method="GET" - Data trong URL
method="POST" - Data ẩn (khuyến khích)
📁

enctype

Cách encode data khi gửi

application/x-www-form-urlencoded (mặc định)
multipart/form-data (cho file upload)

Validation

Client-side validation

novalidate - Tắt validation
Mặc định: Bật HTML5 validation

⌨️ Input Elements

📝 Thẻ <input> - Đa năng nhất

Các loại input phổ biến
<!-- Text inputs -->
<input type="text" name="fullname" placeholder="Họ và tên">
<input type="email" name="email" placeholder="email@example.com" required>
<input type="password" name="password" placeholder="Mật khẩu">
<input type="tel" name="phone" placeholder="0123-456-789">
<input type="url" name="website" placeholder="https://example.com">

<!-- Number & Date inputs -->
<input type="number" name="age" min="18" max="100" step="1">
<input type="range" name="rating" min="1" max="10" value="5">
<input type="date" name="birthday">
<input type="time" name="meeting-time">
<input type="datetime-local" name="appointment">

<!-- Selection inputs -->
<input type="checkbox" name="agree" id="agree" checked>
<input type="radio" name="gender" value="male" id="male">
<input type="radio" name="gender" value="female" id="female">

<!-- File & Hidden inputs -->
<input type="file" name="avatar" accept="image/*">
<input type="hidden" name="user_id" value="123">

<!-- Buttons -->
<input type="submit" value="Gửi form">
<input type="reset" value="Reset">
<input type="button" value="Custom Action">

👁️ Demo các loại input:

📄 Textarea & Select

📝 Thẻ <textarea>

Textarea cho văn bản dài
<!-- Textarea cơ bản -->
<textarea name="message" placeholder="Nhập tin nhắn của bạn..."></textarea>

<!-- Textarea với kích thước và các thuộc tính -->
<textarea 
    name="description" 
    rows="5" 
    cols="50"
    maxlength="500"
    placeholder="Mô tả sản phẩm (tối đa 500 ký tự)"
    required
>Nội dung mặc định ở đây</textarea>

<!-- Textarea không resize -->
<textarea 
    name="comment" 
    style="resize: none; width: 100%; height: 120px;"
    placeholder="Bình luận của bạn..."
></textarea>

📋 Thẻ <select>

Select dropdown và multiple selection
<!-- Select đơn giản -->
<select name="country">
    <option value="">Chọn quốc gia</option>
    <option value="vn">Việt Nam</option>
    <option value="us">United States</option>
    <option value="jp" selected>Japan</option>
</select>

<!-- Select với optgroup -->
<select name="city">
    <option value="">Chọn thành phố</option>
    <optgroup label="Miền Bắc">
        <option value="hanoi">Hà Nội</option>
        <option value="haiphong">Hải Phòng</option>
    </optgroup>
    <optgroup label="Miền Nam">
        <option value="hcm">TP. Hồ Chí Minh</option>
        <option value="cantho">Cần Thơ</option>
    </optgroup>
</select>

<!-- Multiple select -->
<select name="skills" multiple size="5">
    <option value="html">HTML</option>
    <option value="css">CSS</option>
    <option value="js" selected>JavaScript</option>
    <option value="react">React</option>
    <option value="vue" selected>Vue.js</option>
</select>

👁️ Demo Textarea & Select:

Giữ Ctrl (Windows) hoặc Cmd (Mac) để chọn nhiều

🏷️ Labels & Form Organization

🔗 Thẻ <label>

💡 Tại sao cần Label?

Label giúp accessibility tốt hơn, khi click vào label sẽ focus vào input tương ứng, và screen readers có thể đọc được mô tả.

Cách sử dụng label
<!-- Cách 1: Sử dụng for và id -->
<label for="username">Tên đăng nhập:</label>
<input type="text" id="username" name="username">

<!-- Cách 2: Wrap input trong label -->
<label>
    Email:
    <input type="email" name="email">
</label>

<!-- Checkbox và Radio với label -->
<label for="agree">
    <input type="checkbox" id="agree" name="agree">
    Tôi đồng ý với điều khoản sử dụng
</label>

<!-- Radio group -->
<fieldset>
    <legend>Giới tính:</legend>
    <label>
        <input type="radio" name="gender" value="male">
        Nam
    </label>
    <label>
        <input type="radio" name="gender" value="female">
        Nữ
    </label>
</fieldset>

📦 Fieldset & Legend

Nhóm các form elements
<form>
    <fieldset>
        <legend>Thông tin cá nhân</legend>
        <label for="fname">Họ:</label>
        <input type="text" id="fname" name="firstname">
        
        <label for="lname">Tên:</label>
        <input type="text" id="lname" name="lastname">
    </fieldset>

    <fieldset>
        <legend>Thông tin liên hệ</legend>
        <label for="email">Email:</label>
        <input type="email" id="email" name="email">
        
        <label for="phone">Điện thoại:</label>
        <input type="tel" id="phone" name="phone">
    </fieldset>

    <fieldset disabled>
        <legend>Thông tin không thể chỉnh sửa</legend>
        <label for="readonly-info">ID:</label>
        <input type="text" id="readonly-info" value="123456" readonly>
    </fieldset>
</form>

✅ Form Validation

🛡️ HTML5 Validation

HTML5 cung cấp validation built-in không cần JavaScript. Tuy nhiên, luôn cần validation phía server.

Các thuộc tính validation
<form>
    <!-- Required fields -->
    <input type="text" name="name" required placeholder="Tên (bắt buộc)">
    <input type="email" name="email" required placeholder="Email (bắt buộc)">

    <!-- Length validation -->
    <input type="password" name="password" 
           minlength="8" maxlength="20" 
           placeholder="Mật khẩu (8-20 ký tự)">

    <!-- Number validation -->
    <input type="number" name="age" 
           min="18" max="65" 
           placeholder="Tuổi (18-65)">

    <!-- Pattern validation (Regex) -->
    <input type="text" name="phone" 
           pattern="[0-9]{10,11}" 
           placeholder="Số điện thoại (10-11 số)"
           title="Vui lòng nhập 10-11 chữ số">

    <!-- Custom validation messages -->
    <input type="email" name="work-email" 
           pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$"
           title="Email phải có định dạng đúng"
           placeholder="Email công ty">

    <!-- File validation -->
    <input type="file" name="avatar" 
           accept="image/jpeg,image/png,image/gif"
           required>

    <button type="submit">Gửi form</button>
</form>

⚠️ Lưu ý về Validation:

  • Client-side only: HTML5 validation chỉ là UX, không phải security
  • Server validation: Luôn validate lại phía server
  • User experience: Cung cấp error messages rõ ràng
  • Progressive enhancement: Form phải hoạt động kể cả khi JavaScript disabled

💪 Bài tập thực hành

🎯 Bài tập 1: Form đăng ký tài khoản

Yêu cầu bài tập
<!-- 
🎯 YÊU CẦU FORM ĐĂNG KÝ:
1. Form với method="POST" action="#"

2. Fieldset "Thông tin cơ bản":
   - Họ và tên (text, required)
   - Email (email, required)
   - Mật khẩu (password, minlength="8", required)
   - Xác nhận mật khẩu (password, required)
   - Ngày sinh (date, required)

3. Fieldset "Thông tin bổ sung":
   - Giới tính (radio: Nam, Nữ, Khác)
   - Quốc gia (select với 5 quốc gia)
   - Sở thích (checkbox: Đọc sách, Du lịch, Thể thao, Âm nhạc)
   - Giới thiệu bản thân (textarea, maxlength="500")

4. Fieldset "Avatar":
   - Upload ảnh (file, accept="image/*")

5. Checkbox đồng ý điều khoản (required)

6. 2 buttons: Submit "Đăng ký" và Reset "Làm lại"

✅ YÊU CẦU KỸ THUẬT:
- Tất cả input phải có label
- Sử dụng placeholder phù hợp
- Required validation cho các field quan trọng
- Proper form structure với fieldset/legend
-->

<!DOCTYPE html>
<html lang="vi">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Đăng ký tài khoản</title>
</head>
<body>
    <h1>Form Đăng Ký Tài Khoản</h1>
    
    <!-- Viết form của bạn ở đây -->
    
    
    
</body>
</html>

🎯 Bài tập 2: Form liên hệ và feedback

Contact & Feedback Form
<!-- 
📞 YÊU CẦU CONTACT FORM:
1. Form liên hệ:
   - Tên (required)
   - Email (required)
   - Số điện thoại (pattern validation cho VN: 0xxxxxxxxx)
   - Chủ đề (select: Hỗ trợ kỹ thuật, Khiếu nại, Góp ý, Khác)
   - Tin nhắn (textarea, required, minlength="20")

2. Form đánh giá dịch vụ:
   - Đánh giá (radio: Rất tốt, Tốt, Bình thường, Kém, Rất kém)
   - Điểm số (range input 1-10)
   - Sẽ giới thiệu cho bạn bè? (radio: Có, Không)
   - Cải thiện gì? (checkbox multiple: UI/UX, Tốc độ, Tính năng, Giá cả)

3. Newsletter subscription:
   - Đăng ký nhận tin (checkbox)
   - Tần suất (select: Hàng ngày, Hàng tuần, Hàng tháng)

4. Validation:
   - Pattern cho phone: ^0[0-9]{9,10}$
   - Email validation
   - Required fields có dấu * đỏ

💡 BONUS:
- Thêm CSS để form đẹp
- Group related fields với fieldset
- Accessible labels và descriptions
-->

<!-- Tạo contact form của bạn ở đây -->

💡 Tips làm bài tập:

  • 🏷️ Labels: Mỗi input phải có label rõ ràng
  • Validation: Sử dụng required, pattern, minlength hợp lý
  • 📱 UX: Placeholder text hữu ích, không thay thế label
  • 🎯 Accessibility: Đảm bảo tab order logic
  • 🔒 Security: Nhớ rằng client-side validation chỉ là UX
  • 📦 Organization: Dùng fieldset để nhóm related fields

📝 Tổng kết bài học

🎯 Những điều đã học được:

  • Form structure: form, fieldset, legend để tổ chức
  • Input types: text, email, password, number, date, file, etc.
  • Selection: checkbox, radio, select, textarea
  • Labels: Accessibility và UX tốt hơn
  • Validation: HTML5 built-in validation attributes
  • Form submission: action, method, enctype

🚀 Bước tiếp theo:

Trong Bài 5, chúng ta sẽ học về Layout & Containers - cách sử dụng div, span, và các thẻ container để tạo layout cho website.

📐 Tiếp tục Bài 5: Layout →