체크박스를 Shift 키 누른채로 클릭 시 해당 범위가 다 체크되도록 해달라는 요구사항이 있었다.
일단 지금 프로젝트는 Nuxt3으로 구현되어있고, 체크박스는 Nuxt UI의 table 컴포넌트에서 각 row 마다 있는 체크박스였다.
Nuxt UI의 table 컴포넌트는 v-model을 써서 체크박스를 클릭한 아이템을 배열로 받을 수 있게 되어있다!
그리고 Vue의 watch를 활용해서 체크박스의 개수가 변한것을 감지할 수 있다.
더 좋은 방법도 있겠지만, 나는 이렇게 구현했다.
const isShiftKeyDown = ref(false); //변수선언
onMounted(() => {
document.addEventListener('keydown', (event) => {
if (event.key === 'Shift') {
isShiftKeyDown.value = true;
}
});
document.addEventListener('keyup', (event) => {
if (event.key === 'Shift') {
isShiftKeyDown.value = false;
}
});
});
const shiftCheckedArray = ref([]);
watch(
() => checkbox.value,
(to, from) => {
if(checkbox.value !== null && checkbox.value.length > 0) {
const toArr = checkbox.value?.map(item => item.id);
const fromArr = from.map(item => item.id);
const toSubtract = toArr.filter(item => !fromArr.includes(item));
const fromSubstract = fromArr.filter(item => !toArr.includes(item));
const currentClick = toSubtract.length > 0 ? toSubtract : fromSubstract;
shiftCheckedArray.value.push(...currentClick);
// 해당 배열은 2개의 값만 가질 수 있다. (이전 체크박스 id값, 방금 클릭한 체크박스 id값)
if(shiftCheckedArray.value.length > 2) {
shiftCheckedArray.value = shiftCheckedArray.value.slice(-2);
}
// Shift 키 눌렀을때 로직
if (isShiftKeyDown.value) {
to.sort((a, b) => b - a);
from.sort((a, b) => b - a);
// Shift 로 체크 추가
if(to && from &&to.length > 0 && from.length > 0) {
const oldValue = props.list.findIndex((item) => item.id === from[from.length - 1]?.id);
const newValue = props.list.findIndex((item) => item.id === to[to.length - 1]?.id);
if (oldValue !== -1 && newValue !== -1) {
for (let i = (newValue < oldValue ? newValue: oldValue); i < (newValue > oldValue ? newValue + 1 : oldValue + 1); i++) {
const item = checkbox.value.findIndex((item) => item.id === props.list[i].id);
if (item === -1) {
checkbox.value.push(props.list[i]);
checkbox.value.sort((a, b) => b.id - a.id);
}
}
}
}
// Shift 로 체크 제거
if(fromSubstract.length > 0) {
const oldValue = props.list.findIndex((item) => item.id === shiftCheckedArray.value[0]);
const newValue = props.list.findIndex((item) => item.id === shiftCheckedArray.value[1]);
for (let i = (newValue < oldValue ? newValue: oldValue); i < (newValue > oldValue ? newValue + 1 : oldValue + 1); i++) {
const item = checkbox.value.findIndex((item) => item.id === props.list[i].id);
if(item > -1) {
checkbox.value.splice(item, 1);
}
}
}
}
}
}
);
처음엔 쉬운줄 알았는데 하다보니까 머리를 쥐어뜯으면서 했다 🥲
그래도 어디 참고하지않고 내힘으로 개발한 기능이라 너무 뿌듯해서 블로그에 기록용으로 남겨둔당!
미래의 내가보면 뿌듯하겠징,,,
끝~!