jQuery로 checkbox 제어하기

예제 기준 · jQuery : v3.7.1

checkbox는 여러 항목을 고르거나 설정을 켜고 끌 때 자주 사용합니다. 선택한 값 읽기부터 전체 선택, 비활성화까지 필요한 코드를 살펴보겠습니다.

예제의 과일 항목은 name="fruit"로 묶여 있고, 각각의 id와 value는 apple, banana, orange입니다. 각 절의 코드는 따로 실행하며, HTML 요소가 만들어진 뒤 사용합니다. jQuery 코드는 jQuery가 로드된 화면을 기준으로 합니다.

선택된 checkbox 값 읽기

체크된 항목만 찾으려면 선택자에 :checked를 붙입니다. 여러 개를 선택할 수 있으므로 값을 하나씩 읽어 배열에 담습니다.

jQuery

const selected = $('input[name="fruit"]:checked');
const values = [];

for (let i = 0; i < selected.length; i++) {
    values.push($(selected[i]).val());
}

console.log(values);

JavaScript

const selected = document.querySelectorAll('input[name="fruit"]:checked');
const values = [];

for (let i = 0; i < selected.length; i++) {
    values.push(selected[i].value);
}

console.log(values);

Apple과 Orange를 체크하면 ["apple", "orange"], 아무것도 고르지 않으면 빈 배열이 나옵니다. jQuery에서도 여러 요소에 .val()을 한 번 호출하면 첫 요소의 값만 읽으므로 반복해서 가져와야 합니다.

value는 항목에 지정한 값이고 체크 여부는 아닙니다. 체크하지 않은 Apple에서도 $('#apple').val()은 apple을 반환합니다.

과일을 고른 뒤 ‘선택값 읽기’를 눌러 보세요.

checkbox 체크와 체크 해제

현재 체크 상태를 바꿀 때는 jQuery의 .prop('checked', ...)를 사용합니다. true는 체크, false는 해제입니다.

jQuery

const apple = $('#apple');
apple.prop('checked', true);

// 체크를 해제할 때 따로 실행합니다.
// apple.prop('checked', false);

JavaScript

const apple = document.querySelector('#apple');
apple.checked = true;

// 체크를 해제할 때 따로 실행합니다.
// apple.checked = false;

HTML의 checked 속성은 초기 체크 상태를 지정할 때 쓰고, 현재 상태를 읽거나 바꿀 때는 .prop() 또는 .checked를 사용합니다. 상태를 바꾸는 것만으로 change 이벤트가 발생하지는 않습니다.

아래의 ‘전체 초기화’ 버튼은 과일 항목의 체크를 모두 해제합니다.

전체 선택과 전체 해제

전체 선택은 항목들을 한꺼번에 체크하는 것에서 끝나지 않습니다. 개별 항목을 하나 해제하면 전체 선택 표시도 바뀌어야 합니다. 모두 선택했는지와 일부만 선택했는지를 함께 계산합니다.

전체 선택 checkbox는 id="allFruits"를 사용하며 과일 항목의 name="fruit" 그룹에는 포함하지 않습니다. ‘전체 선택’과 ‘전체 해제’ 버튼의 id는 각각 selectAll, clearAll입니다.

jQuery

const all = $('#allFruits');
const fruits = $('input[name="fruit"]');

function updateAllState() {
    const total = fruits.length;
    const count = $('input[name="fruit"]:checked').length;

    all.prop('checked', total > 0 && count === total);
    all.prop('indeterminate', count > 0 && count < total);
}

function setAllChecked(checked) {
    fruits.prop('checked', checked);
    updateAllState();
}

all.on('change', function () {
    setAllChecked(all.prop('checked'));
});
fruits.on('change', updateAllState);

$('#selectAll').on('click', function () {
    setAllChecked(true);
});
$('#clearAll').on('click', function () {
    setAllChecked(false);
});

updateAllState();

JavaScript

const all = document.querySelector('#allFruits');
const fruits = document.querySelectorAll('input[name="fruit"]');

function updateAllState() {
    const total = fruits.length;
    let count = 0;

    for (let i = 0; i < total; i++) {
        if (fruits[i].checked) {
            count += 1;
        }
    }

    all.checked = total > 0 && count === total;
    all.indeterminate = count > 0 && count < total;
}

function setAllChecked(checked) {
    for (let i = 0; i < fruits.length; i++) {
        fruits[i].checked = checked;
    }
    updateAllState();
}

all.addEventListener('change', function () {
    setAllChecked(all.checked);
});
for (let i = 0; i < fruits.length; i++) {
    fruits[i].addEventListener('change', updateAllState);
}

document.querySelector('#selectAll').addEventListener('click', function () {
    setAllChecked(true);
});
document.querySelector('#clearAll').addEventListener('click', function () {
    setAllChecked(false);
});

updateAllState();

indeterminate는 일부만 선택된 상태를 표시합니다. 실제 체크 여부인 checked와는 별개이며, 이 코드에서는 모두 선택됐을 때만 checked를 true로 설정합니다. 항목이 하나도 없으면 전체 선택도 해제 상태로 둡니다.

코드로 여러 항목의 checked를 바꿔도 각 항목의 change 이벤트는 발생하지 않습니다. 그래서 setAllChecked() 마지막에 상태 갱신 함수를 직접 호출했습니다. 이 예제는 처음부터 있는 세 항목을 대상으로 하며, 나중에 항목을 추가하는 화면이라면 조회와 이벤트 연결도 함께 처리해야 합니다.

체크 여부 확인하기

값이 아니라 체크됐는지만 필요할 때는 .is(':checked')로 true 또는 false를 얻을 수 있습니다.

jQuery

const checked = $('#apple').is(':checked');
console.log(checked);

// :checked 선택자로 체크된 요소만 찾을 수도 있습니다.
const selected = $('#apple:checked');
console.log(selected.length > 0);

JavaScript

const apple = document.querySelector('#apple');
const checked = apple.checked;
console.log(checked);

:checked는 요소를 고르는 조건이고, .is(':checked')는 그 조건에 맞는지 확인하는 메서드입니다. 여러 checkbox에 .is(':checked')를 사용하면 하나라도 체크됐을 때 true가 됩니다. 모두 체크됐는지는 앞 절처럼 개수를 비교해야 합니다.

Apple을 체크하거나 해제한 뒤 ‘체크 여부 확인’을 눌러 보세요.

checkbox 비활성화와 활성화

사용자가 체크 상태를 바꾸지 못하게 하려면 disabled를 true로 설정합니다.

jQuery

const apple = $('#apple');
apple.prop('disabled', true);

// 다시 조작할 수 있게 할 때 실행합니다.
// apple.prop('disabled', false);

JavaScript

const apple = document.querySelector('#apple');
apple.disabled = true;

// 다시 조작할 수 있게 할 때 실행합니다.
// apple.disabled = false;

비활성화해도 체크 상태는 유지됩니다. Apple을 체크한 뒤 비활성화하면 체크된 채로 잠기고, 다시 활성화하면 그대로 조작할 수 있습니다. 체크 해제까지 필요하다면 checked도 따로 false로 바꿔야 합니다.

checked 변경과 change 이벤트

사용자가 checkbox를 직접 체크하거나 해제하면 change 이벤트가 발생합니다. 반면 .prop('checked', true)는 상태만 바꿉니다. change에 연결된 처리까지 실행해야 한다면 이벤트를 따로 발생시켜야 합니다.

jQuery

const apple = $('#apple');

apple.on('change', function () {
    console.log('change:', apple.prop('checked'));
});

apple.prop('checked', true); // 체크만 변경
apple.trigger('change'); // change 처리도 필요할 때 호출

JavaScript

const apple = document.querySelector('#apple');

apple.addEventListener('change', function () {
    console.log('change:', apple.checked);
});

apple.checked = true; // 이 대입만으로는 change가 발생하지 않음

const event = new Event('change', {
    bubbles: true
});
apple.dispatchEvent(event);

JavaScript도 checked 변경과 이벤트 발생은 별개입니다. bubbles: true로 만들면 부모 요소에서도 이벤트를 받을 수 있습니다. jQuery의 .trigger('change')가 addEventListener()로 등록한 리스너까지 호출하는 것은 아니므로, 두 방식을 함께 쓸 때는 이벤트를 어떻게 전달할지 구분해야 합니다.

  • Apple을 직접 체크·해제하면 change 로그가 쌓입니다.
  • .prop('checked', true)만 실행하면 체크 상태는 바뀌지만 로그는 추가되지 않습니다.
  • .trigger('change')까지 실행하면 로그가 추가됩니다. 이미 체크된 상태에서도 호출할 때마다 이벤트를 발생시킵니다.

‘로그 지우기’는 기록만 지우며 체크 상태는 유지합니다.

jQuery와 JavaScript 주요 문법 비교

아래의 $box는 jQuery 객체, box는 checkbox DOM 요소입니다.

기능 jQuery JavaScript
값 읽기 $box.val() box.value
체크 여부 $box.is(':checked') box.checked
체크 설정 $box.prop('checked', true) box.checked = true
비활성화 $box.prop('disabled', true) box.disabled = true
일부 선택 표시 $box.prop('indeterminate', true) box.indeterminate = true
change 발생 $box.trigger('change') box.dispatchEvent(event)

checkbox에서는 value, checked, disabled를 구분하면 코드가 단순해집니다. 전체 선택은 개별 항목과의 상태 갱신을 함께 처리하고, 코드로 체크를 바꾼 뒤에는 change 처리도 필요한지 확인하면 됩니다.

참고자료