Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Cách đúng để làm việc với HTML5 checkbox


Cú pháp chuẩn

<input type="checkbox" name="ten_truong" value="gia_tri">
  • name: Tên trường gửi lên server (bắt buộc để submit form)
  • value: Giá trị gửi khi checkbox được check (mặc định "on")
  • checked: Boolean attribute - checked mặc định
  • id: Liên kết với <label for="id"> để click label cũng check

Ví dụ cơ bản

<!DOCTYPE html>
<html lang="vi">
<head>
  <meta charset="UTF-8">
  <title>Checkbox Demo</title>
  <style>
    form { max-width: 400px; margin: 2rem auto; padding: 1.5rem; border: 1px solid #ddd; border-radius: 8px; }
    .checkbox-group { margin-bottom: 1rem; }
    .checkbox-wrapper { display: flex; align-items: center; gap: 0.5rem; cursor: pointer; }
    .checkbox-wrapper input { width: 18px; height: 18px; accent-color: #3498db; }
    .checkbox-wrapper label { margin: 0; cursor: pointer; user-select: none; }
    .checkbox-wrapper input:focus + label { outline: 2px solid #3498db; border-radius: 2px; }
    fieldset { border: 1px solid #ddd; border-radius: 8px; padding: 1rem; margin-bottom: 1rem; }
    legend { font-weight: 600; padding: 0 0.5rem; }
    button { width: 100%; padding: 0.75rem; background: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem; }
    button:hover { background: #2980b9; }
    pre { background: #f8f9fa; padding: 1rem; border-radius: 4px; overflow-x: auto; }
  </style>
</head>
<body>
  <form id="demoForm" action="/submit" method="POST">
    <fieldset>
      <legend>Môn học (Multiple choice)</legend>
      
      <div class="checkbox-group">
        <div class="checkbox-wrapper">
          <input type="checkbox" id="math" name="subjects" value="math">
          <label for="math">Toán học</label>
        </div>
      </div>
      
      <div class="checkbox-group">
        <div class="checkbox-wrapper">
          <input type="checkbox" id="physics" name="subjects" value="physics" checked>
          <label for="physics">Vật lý</label>
        </div>
      </div>
      
      <div class="checkbox-group">
        <div class="checkbox-wrapper">
          <input type="checkbox" id="chemistry" name="subjects" value="chemistry">
          <label for="chemistry">Hóa học</label>
        </div>
      </div>
    </fieldset>
    
    <fieldset>
      <legend>Điều khoản</legend>
      <div class="checkbox-group">
        <div class="checkbox-wrapper">
          <input type="checkbox" id="terms" name="terms" value="accepted" required>
          <label for="terms">Tôi đồng ý với <a href="#">Điều khoản sử dụng</a></label>
        </div>
      </div>
    </fieldset>
    
    <button type="submit">Gửi đăng ký</button>
  </form>
  
  <div id="result" style="max-width: 400px; margin: 2rem auto; display: none;">
    <h3>Dữ liệu gửi đi (FormData):</h3>
    <pre id="formDataOutput"></pre>
  </div>

  <script>
    document.getElementById('demoForm').addEventListener('submit', (e) => {
      e.preventDefault();
      const formData = new FormData(e.target);
      const output = {};
      
      // Checkbox có thể có nhiều giá trị cùng name
      for (const [key, value] of formData.entries()) {
        if (!output[key]) output[key] = [];
        output[key].push(value);
      }
      
      document.getElementById('formDataOutput').textContent = JSON.stringify(output, null, 2);
      document.getElementById('result').style.display = 'block';
    });
  </script>
</body>
</html>

Xử lý Checkbox với JavaScript

1. Lấy giá trị (Checked/Unchecked)

const checkbox = document.getElementById('myCheckbox');

// Kiểm tra trạng thái
checkbox.checked; // true/false

// Lấy giá trị nếu checked
const value = checkbox.checked ? checkbox.value : null;

// Lấy tất cả checkbox cùng name (NodeList)
const checkboxes = document.querySelectorAll('input[name="subjects"]:checked');
const values = Array.from(checkboxes).map(cb => cb.value); // ['math', 'physics']

2. Thiết lập trạng thái

checkbox.checked = true;   // Check
checkbox.checked = false;  // Uncheck
checkbox.indeterminate = true; // Trạng thái indeterminate (gạch ngang, chỉ qua JS)

3. Event handling

// Change event (khi user click)
checkbox.addEventListener('change', (e) => {
  console.log('Checked:', e.target.checked);
  console.log('Value:', e.target.value);
});

// Form submit - lấy FormData
form.addEventListener('submit', (e) => {
  e.preventDefault();
  const formData = new FormData(form);
  
  // Checkbox unchecked KHÔNG xuất hiện trong FormData
  // Checkbox checked: xuất hiện với value
  for (const [key, value] of formData.entries()) {
    console.log(key, value);
  }
});

Checkbox Group - "Check All" Pattern

<fieldset>
  <legend>
    <div class="checkbox-wrapper">
      <input type="checkbox" id="checkAll">
      <label for="checkAll">Chọn tất cả</label>
    </div>
  </legend>
  
  <div class="checkbox-group">
    <div class="checkbox-wrapper">
      <input type="checkbox" name="items" value="item1" class="item-check">
      <label>Mục 1</label>
    </div>
    <div class="checkbox-wrapper">
      <input type="checkbox" name="items" value="item2" class="item-check">
      <label>Mục 2</label>
    </div>
    <div class="checkbox-wrapper">
      <input type="checkbox" name="items" value="item3" class="item-check">
      <label>Mục 3</label>
    </div>
  </div>
</fieldset>

<script>
const checkAll = document.getElementById('checkAll');
const itemChecks = document.querySelectorAll('.item-check');

checkAll.addEventListener('change', () => {
  itemChecks.forEach(cb => cb.checked = checkAll.checked);
  updateCheckAllState();
});

itemChecks.forEach(cb => {
  cb.addEventListener('change', updateCheckAllState);
});

function updateCheckAllState() {
  const checked = document.querySelectorAll('.item-check:checked').length;
  const total = itemChecks.length;
  
  if (checked === 0) {
    checkAll.checked = false;
    checkAll.indeterminate = false;
  } else if (checked === total) {
    checkAll.checked = true;
    checkAll.indeterminate = false;
  } else {
    checkAll.checked = false;
    checkAll.indeterminate = true; // Trạng thái "mixed"
  }
}
</script>

Accessibility (Khả năng tiếp cận)

  • Luôn dùng <label for="id"> bao quanh hoặc liên kết với checkbox
  • Dùng <fieldset> + <legend> cho group liên quan
  • required trên checkbox: ít nhất một phải check (cho group cùng name)
  • Keyboard: Tab để focus, Space để toggle
  • ARIA: role="checkbox" chỉ cần cho custom checkbox (div span), input native không cần

Styling tùy chỉnh (Custom Checkbox)

/* Ẩn checkbox gốc, style label::before */
.custom-checkbox {
  position: relative;
  padding-left: 2.5rem;
  cursor: pointer;
}

.custom-checkbox input {
  position: absolute;
  opacity: 0;
  width: 0; height: 0;
}

.custom-checkbox .checkmark {
  position: absolute;
  top: 0; left: 0;
  width: 1.25rem; height: 1.25rem;
  background: white;
  border: 2px solid #ccc;
  border-radius: 4px;
  transition: all 0.2s;
}

.custom-checkbox input:checked ~ .checkmark {
  background: #3498db;
  border-color: #3498db;
}

.custom-checkbox .checkmark::after {
  content: "";
  position: absolute;
  display: none;
  left: 0.4rem; top: 0.15rem;
  width: 0.25rem; height: 0.5rem;
  border: solid white;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.custom-checkbox input:checked ~ .checkmark::after {
  display: block;
}

/* Focus visible */
.custom-checkbox input:focus-visible ~ .checkmark {
  box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.4);
}