EditableSelect 입력 가능한 드롭다운 선택 상자
입력과 드롭다운 선택을 동시에 지원하는 입력 컴포넌트예요.
출처: 문서
본문
언제 사용하나요
사용자가 데이터를 직접 입력하는 것과 기존 데이터에서 고르는 것을 모두 지원해야 할 때 사용해요. 입력 연상(자동완성) 기능을 더해 기존 데이터를 검색하기 편하게 만들 수 있어요.
기본 사용법
v-model의 값은 현재 선택된 value 속성 값이에요. :::demo
<template>
<d-editable-select v-model="value" :options="options" :width="450"></d-editable-select>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const options = reactive([
{
label: 'label0',
value: 'label0',
},
{
label: 'label1',
value: 'label1',
},
{
label: 'label2',
value: 'label2',
},
]);
return {
value,
options,
};
},
});
</script>
:::
크기
sm, md, lg 세 가지 크기를 지원하고, 기본값은 md예요. :::demo
<template>
<h5>small</h5>
<d-editable-select v-model="value" :options="options" :width="450" size="sm"></d-editable-select>
<h4>middle</h4>
<d-editable-select v-model="value" :options="options" :width="450"></d-editable-select>
<h3>large</h3>
<d-editable-select v-model="value" :options="options" :width="450" size="lg"></d-editable-select>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const options = reactive([
{
label: 'label0',
value: 'label0',
},
{
label: 'label1',
value: 'label1',
},
{
label: 'label2',
value: 'label2',
},
]);
return {
value,
options,
};
},
});
</script>
:::
선택기 자체 비활성화
선택기 컴포넌트 전체를 비활성화해요.
disabled 속성을 설정하면 선택기 전체를 사용할 수 없게 돼요. :::demo
<template>
<d-row type="flex">
<d-col :flex="4">
<d-editable-select v-model="value" :disabled="isDisabled" :width="450" :options="options"></d-editable-select>
</d-col>
<d-col :flex="2">
<d-button id="primaryBtn" @click="toggle" style="margin-left:10px">
{{ isDisabled ? 'Enable EditableSelect' : 'Disable EditableSelect' }}
</d-button>
</d-col>
</d-row>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const options = reactive([
{
label: 'label0',
value: 'label0',
},
{
label: 'label1',
value: 'label1',
},
{
label: 'label2',
value: 'label2',
},
]);
const isDisabled = ref(false);
const toggle = () => {
isDisabled.value = !isDisabled.value;
};
return {
value,
options,
isDisabled,
toggle,
};
},
});
</script>
:::
비활성화 옵션이 있는 경우
disabled-key 값을 설정해 비활성화할 옵션의 Key 값을 직접 지정할 수 있어요.
:::demo
<template>
<d-editable-select v-model="value" :width="450" :options="options" disabled-key="disabled"></d-editable-select>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const options = reactive([
{
label: 'label0',
value: 'label0',
disabled: true,
},
{
label: 'label1',
value: 'label1',
},
{
label: 'label2',
value: 'label2',
},
]);
return {
value,
options,
};
},
});
</script>
:::
선택 초기화(클리어) 기능
선택기를 초기 상태로 비울 수 있어요.
allow-clear 속성을 설정하면 선택기를 비울 수 있어요. :::demo
<template>
<d-editable-select v-model="value" :width="450" :options="options" allow-clear @input-change="handleInputChange"></d-editable-select>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const options = reactive([
{
label: 'label0',
value: 'label0',
},
{
label: 'label1',
value: 'label1',
},
{
label: 'label2',
value: 'label2',
},
]);
const handleInputChange = (val) => {
console.log(val);
};
return {
value,
options,
handleInputChange,
};
},
});
</script>
:::
커스텀 필터 메서드
로컬 검색에 사용할 필터 메서드를 직접 정의할 수 있고, 로컬 검색에서만 동작해요. :::demo
<template>
<d-editable-select v-model="value" :width="450" :options="options" :filter-method="filterMethod"></d-editable-select>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const filterMethod = (query) => {
if (query) {
options.value = options.value.filter((item) => {
return item.label.toLowerCase().indexOf(query.toLowerCase()) !== -1;
});
} else {
options.value = [];
}
};
let options = ref([
{
label: 'label0',
value: 'label0',
},
{
label: 'label1',
value: 'label1',
},
{
label: 'label2',
value: 'label2',
},
]);
return {
value,
options,
filterMethod,
};
},
});
</script>
:::
커스텀 템플릿 표시
개별 옵션이 어떻게 렌더링될지와, 매칭되는 데이터가 없을 때 보여줄 템플릿을 직접 정의할 수 있어요.
:::demo
<template>
<d-editable-select v-model="value" :width="450" :options="options">
<template #item="slotProps">
<div>第{{ slotProps.index }}项: {{ slotProps.option.label }}</div>
</template>
<template>
<div>没有匹配项</div>
</template>
</d-editable-select>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const options = reactive([
{
label: 'label0',
value: 'label0',
},
{
label: 'label1',
value: 'label1',
},
{
label: 'label2',
value: 'label2',
},
]);
return {
value,
options,
};
},
});
</script>
:::
원격 검색
입력한 키워드로 서버에서 데이터를 검색해요.
원격 검색을 활성화하려면 remote-method를 넘겨야 해요. remote-method는 Function이고, 입력값이 바뀔 때 호출되며 인자로 현재 입력값을 받아요.
:::demo
<template>
<d-editable-select
remote
enable-lazy-load
v-model="value"
:max-height="300"
:width="450"
:options="options"
:loading="loading"
:remote-method="remoteMethod"
@load-more="loadMore"
>
</d-editable-select>
</template>
<script>
import { defineComponent, ref, reactive } from 'vue';
export default defineComponent({
setup() {
const value = ref('');
const search = ref('');
const options = ref([]);
const loading = ref(false);
let index = 0;
let timer = null;
const fetch = () => {
loading.value = true;
return new Promise((resolve) => {
const data = [];
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(() => {
for (let i = 0; i < 15; i++) {
data.push({
label: `label${i + index}`,
value: i + index,
});
}
loading.value = false;
resolve(data);
}, 2000);
});
};
const remoteMethod = async (query) => {
search.value = query;
let list = await fetch();
if (query) {
options.value = list.filter((item) => {
return item.label.toLowerCase().includes(query.toLowerCase());
});
} else {
options.value.splice(0, options.value.length);
}
};
const loadMore = async () => {
index += 15;
let list = await fetch();
options.value = options.value.concat(
list.filter((item) => {
return item.label.toLowerCase().includes(search.value.toLowerCase());
})
);
};
return {
value,
options,
loading,
loadMore,
remoteMethod,
};
},
});
</script>
:::
EditableSelect 파라미터
| 파라미터 | 타입 | 기본값 | 설명 | Demo 링크 |
|---|---|---|---|---|
| model-value / v-model | string | number |
'' | 선택, 선택 항목 바인딩 값 | 기본 사용법 |
| options | Options | [] | 선택, 데이터 리스트 | 기본 사용법 |
| allow-clear | boolean |
false | 선택, 옵션 비우기 가능 여부 | 기본 사용법 |
| size | string |
'md' | 선택, 입력창 크기. 'lg', 'md', 'sm' 세 가지 | 크기 |
| placeholder | string |
'Select' | 선택, 입력창 기본 힌트 텍스트 | 기본 사용법 |
| width | number |
-- | 선택, 입력창 너비 | 기본 사용법 |
| max-height | number |
-- | 선택, 드롭다운 최대 높이 | 기본 사용법 |
| disabled | boolean |
false | 선택, 선택기 자체 비활성화 여부 | 선택기 자체 비활성화 |
| disabled-key | string |
'' | 선택, 비활성화 옵션의 Key 값 설정 | 옵션 비활성화 |
| enable-lazy-load | boolean |
false | 선택, 지연 로딩 허용 여부 | 원격 검색 |
| filter-method | (inputValue:string)=>Array<Options> |
-- | 선택, 필터 메서드 커스텀 | 커스텀 매칭 메서드 |
| remote-method | (inputValue:string)=>Array<Options> |
-- | 선택, 원격 검색 메서드 커스텀 | 원격 검색 |
| show-glow-style | boolean |
true | 선택, 호버 발광 효과 표시 여부 | |
| max-length | number |
-- | 선택, 입력창 최대 입력 길이 |
EditableSelect 이벤트
| 이벤트명 | 콜백 파라미터 | 설명 | Demo 링크 |
|---|---|---|---|
| load-more | (inputvalue:string)=>void |
선택, 지연 로딩 트리거 이벤트 | 원격 검색 |
| focus | (e: FocusEvent)=>void |
선택, input 포커스 획득 시 트리거 | |
| blur | (e: FocusEvent)->void |
선택, input 포커스 상실 시 트리거 | |
| change | (value:string|number)=>void |
선택, 선택 값 변경 시 트리거 | |
| visible-change | (visible:boolean)=>void |
선택, 드롭다운 표시/숨김 시 트리거 | |
| input-change | (inputvalue:string)=>void |
선택, 입력창 입력 시 트리거 | 옵션 비우기 |
EditableSelect 슬롯
| 슬롯명 | 설명 | Demo 링크 |
|---|---|---|
| item | 선택, 드롭다운 메뉴 항목 템플릿 | 커스텀 템플릿 표시 |
| noResultItem | 선택, 드롭다운 메뉴 항목 검색 후 결과가 없을 때의 템플릿 | 커스텀 템플릿 표시 |
EditableSelect 타입 정의
Options
export type Option = {
label: string;
value: string | number;
disabled?: boolean;
[key: string]: unknown;
};
export type Options = Array<Option>;
더 알아보기 (Learn more)
입력과 선택을 동시에 지원하는 컴포넌트로, filter-method와 remote-method로 검색 동작을 직접 정의할 수 있어요. #item 슬롯으로 옵션 렌더링을 커스텀하고, enable-lazy-load로 스크롤 시 추가 데이터를 불러올 수도 있어요.