Skip to content

Commit f9fce84

Browse files
authored
Merge pull request #85 from TaskFlow-CLAP/CLAP-262
CLAP-262 useOutsideClick 커스텀 훅 구현
2 parents f2f1e34 + 01929c4 commit f9fce84

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

src/components/filters/FilterCategory.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<div class="filter-container grow">
44
<span class="filter-title">1차 카테고리</span>
55
<div
6+
ref="mainRef"
67
class="filter-dropdown"
78
@click="toggleDropdown('main')">
89
<span class="grow text-center">선택</span>
@@ -31,6 +32,7 @@
3132
<div class="filter-container grow">
3233
<span class="filter-title">2차 카테고리</span>
3334
<div
35+
ref="subRef"
3436
class="filter-dropdown"
3537
:class="isDisabled ? 'bg-background-2 text-disabled' : 'text-black'"
3638
@click="!isDisabled && toggleDropdown('sub')">
@@ -77,6 +79,7 @@ import { dropdownIcon } from '@/constants/iconPath'
7779
import type { Category, FilterCategoryProps } from '@/types/common'
7880
import { computed, ref, watchEffect } from 'vue'
7981
import CommonIcons from '../common/CommonIcons.vue'
82+
import { useOutsideClick } from '../hooks/useOutsideClick'
8083
8184
const { categoryList = [], main, sub } = defineProps<FilterCategoryProps>()
8285
const emit = defineEmits(['update:main', 'update:sub'])
@@ -121,4 +124,7 @@ const onMainClick = (category: Category) => {
121124
const onSubClick = (value: number) => {
122125
emit('update:sub', value)
123126
}
127+
128+
const { htmlRef: mainRef } = useOutsideClick(() => isMainOpened.value && toggleDropdown('main'))
129+
const { htmlRef: subRef } = useOutsideClick(() => isSubOpened.value && toggleDropdown('sub'))
124130
</script>

src/components/filters/FilterDropdown.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
:class="width === 'full' && 'grow'">
66
<span class="filter-title">{{ title }}</span>
77
<div
8+
ref="htmlRef"
89
class="filter-dropdown"
910
@click="toggleDropdown">
1011
<span class="grow text-center">{{
@@ -32,6 +33,7 @@ import type { Filter } from '@/types/common'
3233
import { ref } from 'vue'
3334
import { dropdownIcon } from '@/constants/iconPath'
3435
import CommonIcons from '../common/CommonIcons.vue'
36+
import { useOutsideClick } from '../hooks/useOutsideClick'
3537
3638
const { title, value, width = '120', optionList } = defineProps<Filter>()
3739
const emit = defineEmits(['update:value'])
@@ -43,4 +45,6 @@ const onOptionClick = (option: string) => {
4345
emit('update:value', option)
4446
toggleDropdown()
4547
}
48+
49+
const { htmlRef } = useOutsideClick(() => isDropdownOpened.value && toggleDropdown())
4650
</script>

src/components/filters/FilterDropdownMulti.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
:class="width === 'full' && 'grow'">
66
<span class="filter-title">{{ title }}</span>
77
<div
8+
ref="htmlRef"
89
class="filter-dropdown"
910
@click="toggleDropdown">
1011
<span class="grow text-center">선택</span>
@@ -35,6 +36,7 @@ import type { Filter } from '@/types/common'
3536
import { ref } from 'vue'
3637
import { dropdownIcon } from '@/constants/iconPath'
3738
import CommonIcons from '../common/CommonIcons.vue'
39+
import { useOutsideClick } from '../hooks/useOutsideClick'
3840
3941
const { title, width = '120', optionList, value } = defineProps<Filter>()
4042
const emit = defineEmits(['update:value'])
@@ -45,4 +47,6 @@ const toggleDropdown = () => (isDropdownOpened.value = !isDropdownOpened.value)
4547
const onOptionClick = (option: string | number) => {
4648
emit('update:value', option)
4749
}
50+
51+
const { htmlRef } = useOutsideClick(toggleDropdown)
4852
</script>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { onMounted, onUnmounted, ref } from 'vue'
2+
3+
export const useOutsideClick = (onClick: () => void) => {
4+
const htmlRef = ref<HTMLElement | null>(null)
5+
6+
const onOutsideClick = (event: MouseEvent) => {
7+
if (htmlRef.value && !htmlRef.value.contains(event.target as Node)) {
8+
onClick()
9+
}
10+
}
11+
12+
onMounted(() => {
13+
window.addEventListener('click', onOutsideClick)
14+
})
15+
onUnmounted(() => {
16+
window.removeEventListener('click', onOutsideClick)
17+
})
18+
return { htmlRef }
19+
}

0 commit comments

Comments
 (0)