Skip to content

FilterMultiDropdown

기본 사용법

FilterMultiDropdown은 필터링 기능이 추가된 다중 선택 드롭다운 컴포넌트입니다. 사용자는 검색어를 입력하여 목록을 필터링할 수 있으며, 여러 항목을 선택할 수 있습니다. 선택된 항목은 드롭다운 버튼에 표시됩니다.

vue
<script setup lang="ts">
import { ref, computed } from 'vue';
import {
    FilterMultiDropdown,
    ICON_TYPE,
} from '@jennifersoft/vue-components-v2';

const sampleItems = [
    { label: '딸기', value: 'strawberry' },
    { label: '딸기우유', value: 'strawberry_milk' },
    { label: '딸기케이크', value: 'strawberry_cake' },
    { label: '딸기아이스크림', value: 'strawberry_ice' },
    { label: '초코', value: 'choco' },
    { label: '초코우유', value: 'choco_milk' },
    { label: '초코케이크', value: 'choco_cake' },
    { label: '초코아이스크림', value: 'choco_ice', disabled: true },
    { label: '바나나', value: 'banana' },
    { label: '바나나우유', value: 'banana_milk' },
    { label: '바나나케이크', value: 'banana_cake' },
    { label: '바나나아이스크림', value: 'banana_ice' },
    { label: '사과주스', value: 'apple_juice' },
    { label: '사과파이', value: 'apple_pie' },
    { label: '사과잼', value: 'apple_jam' },
];

const selectedItems = ref([]);
const isOpen = ref(false);
const searchKeyword = ref('');
const filteredItems = computed(() => {
    if (!searchKeyword.value) return sampleItems;
    return sampleItems.filter((item) =>
        item.label.toLowerCase().includes(searchKeyword.value.toLowerCase())
    );
});
</script>
<template>
    <filter-multi-dropdown
        v-model:selected-list="selectedItems"
        v-model:open="isOpen"
        v-model:search-keyword="searchKeyword"
        :list="filteredItems"
        title="과일 선택"
        :text="{
            selectAllItemLabel: '전체 선택',
            whenFilterEmpty: '과일을 선택하세요',
            noResult: '검색 결과가 없습니다',
        }"
        :leading-icon="ICON_TYPE.search"
    />
</template>

타입(Type) 스타일

Outlined(기본)와 Contained(배경 채움) 두 가지 스타일을 지원합니다.

vue
<script setup lang="ts">
import { ref, computed } from 'vue';
import { FilterMultiDropdown, ICON_TYPE } from '@jennifersoft/vue-components-v2';

const sampleItems = [
    { label: '딸기', value: 'strawberry' },
    { label: '딸기우유', value: 'strawberry_milk' },
    // ...
];

const selectedItemsTypeOutlined = ref([]);
const selectedItemsTypeContained = ref([]);
const isOpenTypeOutlined = ref(false);
const isOpenTypeContained = ref(false);
const searchKeywordTypeOutlined = ref('');
const searchKeywordTypeContained = ref('');

const filteredItemsTypeOutlined = computed(() => {
    if (!searchKeywordTypeOutlined.value) return sampleItems;
    return sampleItems.filter((item) =>
        item.label.toLowerCase().includes(searchKeywordTypeOutlined.value.toLowerCase())
    );
});
const filteredItemsTypeContained = computed(() => {
    if (!searchKeywordTypeContained.value) return sampleItems;
    return sampleItems.filter((item) =>
        item.label.toLowerCase().includes(searchKeywordTypeContained.value.toLowerCase())
    );
});
</script>
<template>
    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
        <filter-multi-dropdown
            v-model:selected-list="selectedItemsTypeOutlined"
            v-model:open="isOpenTypeOutlined"
            v-model:search-keyword="searchKeywordTypeOutlined"
            :list="filteredItemsTypeOutlined"
            title="Outlined (기본)"
            type="outlined"
            :text="{
                selectAllItemLabel: '전체 선택',
                whenFilterEmpty: '과일을 선택하세요',
                noResult: '검색 결과가 없습니다',
                noList: '목록이 없습니다',
            }"
            :leading-icon="ICON_TYPE.search"
        />
        <filter-multi-dropdown
            v-model:selected-list="selectedItemsTypeContained"
            v-model:open="isOpenTypeContained"
            v-model:search-keyword="searchKeywordTypeContained"
            :list="filteredItemsTypeContained"
            title="Contained"
            type="contained"
            :text="{
                selectAllItemLabel: '전체 선택',
                whenFilterEmpty: '과일을 선택하세요',
                noResult: '검색 결과가 없습니다',
                noList: '목록이 없습니다',
            }"
            :leading-icon="ICON_TYPE.search"
        />
    </div>
</template>

Props

이름타입기본값설명
listArray<{ label: string, value: PropertyKey, disabled?: boolean }>[]드롭다운 메뉴에 표시할 항목 목록
titlestringundefined드롭다운 라벨 (선택사항)
text{ selectAllItemLabel: string, whenFilterEmpty: string, noResult: string }-텍스트 라벨 설정 객체
leadingIconIconTypesundefined입력 필드 왼쪽에 표시할 아이콘 (선택사항)
type'outlined' | 'contained''outlined'입력 박스 스타일(외곽선/채움)
visibleRowsnumber10드롭다운 메뉴에 표시할 최대 행 수

v-model

이름타입기본값설명
openbooleanfalse드롭다운 메뉴의 열림 상태
selectedListPropertyKey[][]선택된 항목 값들의 배열
searchKeywordstring''현재 검색 키워드

이벤트

이름파라미터설명
update:selectedListPropertyKey[]선택된 항목이 변경될 때 발생
update:searchKeywordstring검색 키워드가 변경될 때 발생

검색 및 필터링 기능

FilterMultiDropdown은 사용자가 검색어를 입력하면 목록을 실시간으로 필터링합니다. 필터링된 목록에 대해 전체 선택 옵션도 제공됩니다.

2
vue
<script setup lang="ts">
import { ref, computed } from 'vue';
import {
    FilterMultiDropdown,
    FloatLabel,
    ICON_TYPE,
} from '@jennifersoft/vue-components-v2';

const selectedItems = ref([]);
const isOpen = ref(false);
const searchKeyword = ref('');

// 샘플 아이템 목록
const sampleItems = [
    { label: '딸기', value: 'strawberry' },
    { label: '딸기우유', value: 'strawberry_milk' },
    { label: '초코', value: 'choco' },
    { label: '초코우유', value: 'choco_milk' },
    /* ... 그 외 여러 항목들 */
];

const filteredItems = computed(() => {
    if (!searchKeyword.value) return sampleItems;
    return sampleItems.filter((item) =>
        item.label.toLowerCase().includes(searchKeyword.value.toLowerCase())
    );
});
</script>
<template>
    <float-label fixed position="on">
        <filter-multi-dropdown
            v-model:selected-list="selectedItems"
            v-model:open="isOpen"
            v-model:search-keyword="searchKeyword"
            :list="filteredItems"
            title="과일 필터"
            :text="{
                selectAllItemLabel: '모든 과일 선택',
                whenFilterEmpty: '과일 필터링하기',
                noResult: '검색 결과가 없습니다',
            }"
            :leading-icon="ICON_TYPE.filter"
        />
        <label>과일 필터</label>
    </float-label>
</template>

빈 리스트 처리

FilterMultiDropdown은 리스트가 비어 있을 때 적절한 메시지를 표시합니다. 검색어가 있는 경우는 "검색 결과가 없습니다"라는 메시지가, 검색어가 없는 경우는 리스트가 비어 있다는 것을 알립니다.

vue
<script setup lang="ts">
import { ref } from 'vue';
import {
    FilterMultiDropdown,
    ICON_TYPE,
} from '@jennifersoft/vue-components-v2';

const emptySelectedItems = ref([]);
const isEmptyOpen = ref(false);
const emptySearchKeyword = ref('');
</script>
<template>
    <filter-multi-dropdown
        v-model:selected-list="emptySelectedItems"
        v-model:open="isEmptyOpen"
        v-model:search-keyword="emptySearchKeyword"
        :list="[]"
        title="빈 리스트 예시"
        :text="{
            selectAllItemLabel: '전체 선택',
            whenFilterEmpty: '항목이 없습니다',
            noResult: '검색 결과가 없습니다',
            noList: '리스트가 없습니다',
        }"
        :leading-icon="ICON_TYPE.list"
    />
</template>

크기(Size) 설정 예시

FilterMultiDropdown 컴포넌트는 'small', 'medium', 'large' 세 가지 크기 옵션을 지원합니다. 기본값은 'medium'입니다.

vue
<script setup lang="ts">
import { ref, computed } from 'vue';
import {
    FilterMultiDropdown,
    ICON_TYPE,
} from '@jennifersoft/vue-components-v2';

const selectedItems = ref([]);
const isOpen = ref(false);
const searchKeyword = ref('');

// 샘플 아이템 목록
const sampleItems = [
    /* 아이템 목록 */
];

const filteredItems = computed(() => {
    if (!searchKeyword.value) return sampleItems;
    return sampleItems.filter((item) =>
        item.label.toLowerCase().includes(searchKeyword.value.toLowerCase())
    );
});
</script>
<template>
    <filter-multi-dropdown
        v-model:selected-list="selectedItems"
        v-model:open="isOpen"
        v-model:search-keyword="searchKeyword"
        :list="filteredItems"
        title="과일 선택"
        size="large"
        :text="{
            selectAllItemLabel: '전체 선택',
            whenFilterEmpty: '과일을 선택하세요',
            noResult: '검색 결과가 없습니다',
        }"
        :leading-icon="ICON_TYPE.search"
    />
</template>

접근성

기능
방향키 ↑ / ↓메뉴 항목 포커스를 한 단계씩 이동
Alt + ↑ / Alt + ↓메뉴 항목 포커스를 5개씩 이동 (macOS에서는 Option 키)
Ctrl + ↑ / Ctrl + ↓가장 처음 / 마지막 메뉴 항목으로 이동 (macOS에서는 Command 키)
Home가장 처음 메뉴 항목으로 이동
End가장 마지막 메뉴 항목으로 이동
Enter현재 포커스된 메뉴 항목 선택 또는 선택 해제
Escape드롭다운 메뉴 닫기