Va.Filterbox — 타이핑으로 실시간 필터링되는 드롭다운
Va.Combobox가 "옵션에서 선택"이라면, Va.Filterbox는 "옵션이 많을 때 타이핑으로 좁혀 찾아 선택" 하는 컴포넌트입니다. 코드 구조는 Combobox와 판박이지만, 자유 입력 + 실시간 필터링 로직이 추가되어 있어 옵션이 수십·수백 개일 때 진가를 발휘합니다.
- 클래스: Va.Filterbox — va_component.js:2841
- short name: filterbox
- 상속: Va.PureField (Combobox와 형제)
- isContainer: true
- 베이스 CSS: va-filterbox (팝업은 va-menu-pop)
- 소스 크기: 약 1632줄 — Combobox와 함께 최대 크기

1. 기본 사용
{
tagName: 'filterbox',
data: [
{ key: 'US', display: 'United States' },
{ key: 'KR', display: 'South Korea' },
{ key: 'JP', display: 'Japan' },
{ key: 'CN', display: 'China' }
// ... 200개국
],
filterKeys: ['display'], // display 필드로 필터링
isFilterRuntime: true, // 타이핑마다 실시간 필터
value: 'KR',
onSelect: 'onCountrySelect'
}
필드에 "kor"을 치면 팝업 리스트가 "Korea" 포함 항목만 표시됩니다.
2. Va.Combobox와의 차이
두 컴포넌트는 소스가 거의 판박이라 차이만 정확히 아는 게 실용적입니다.
항목Va.ComboboxVa.Filterbox
| 필드 편집 | readonly (팝업 조작만) | 자유 입력 가능 — 타이핑 허용 |
| 필터링 로직 | 없음 | filter() 메서드로 데이터 좁힘 |
| filterKeys | ✕ | ✓ (필터 대상 필드명 배열) |
| isFilterRuntime | ✕ | ✓ (true면 타이핑마다 자동 필터) |
| Enter 키 동작 | 팝업 열기/선택 | Enter로 필터 실행 + 팝업 열기 |
| ↓ 화살표 시 | 팝업 열림 + 첫 항목 포커스 | 팝업 열려 있으면 첫 항목 포커스만 |
| rowHeight 기본 | 34 | 30 (약간 얇음) |
| CSS 클래스 | va-input | va-filterbox |
한 줄 요약: "옵션이 많을 때 타이핑으로 찾는 콤보박스."
3. Filterbox 전용 속성
Combobox 속성 전체 + 필터 관련 3개 추가:
속성기본값설명
| filterKeys | ['display'] | 필터링 대상 필드명 배열. 여러 필드에서 매칭하려면 ['key', 'display', 'name'] 같이 |
| isFilterRuntime | false | true면 타이핑할 때마다 자동 필터 (실시간). false면 Enter 눌러야 필터 |
| editable | false | 자유 입력 데이터로도 값 확정 허용 |
나머지 속성(data, key, display, template, multiSelect, popMaxHeight, popWidth, addCheckAll, dataMode 등)은 Combobox와 동일.
4. filterKeys — 어떤 필드에서 검색할지
{
tagName: 'filterbox',
filterKeys: ['name', 'email', 'department'], // 3개 필드 중 아무거나 매칭
data: [
{ key: '1', name: '홍길동', email: 'hong@ex.com', department: '개발' },
{ key: '2', name: '김철수', email: 'kim@ex.com', department: '기획' }
]
}
사용자가 "hong" 치면 email로 매칭, "개발" 치면 department로 매칭. 실무에서 자주 쓰는 패턴.
5. isFilterRuntime — 실시간 vs Enter
두 모드의 UX 차이:
isFilterRuntime: false (기본)
- 사용자가 타이핑 → 필드에만 텍스트 반영
- Enter 눌러야 필터 실행 + 팝업 표시
- 이유: 대량 데이터에서 매 keystroke 필터링 부담 방지
isFilterRuntime: true
- 사용자가 타이핑 → 100ms debounce 후 자동 필터 (va_component.js:3177-3182)
- 즉각적인 UX, 소량~중량 데이터에 적합
// 실시간 필터 (수백 건까지)
{ tagName: 'filterbox', isFilterRuntime: true, data: [...] }
// 대량 데이터, Enter로만 (수천 건)
{ tagName: 'filterbox', data: [...] }
6. 필터 로직 (filter() 메서드)
filter(inputValue){
this.dataManager.filter((item) => {
for(let i=0; i < this.filterKeys.length; i++){
if(item[this.filterKeys[i]].indexOf(inputValue) != -1){
return true; // 하나라도 매칭되면 표시
}
}
return false;
});
this.applyData();
}
특징:
- 부분 문자열 매칭 (indexOf !== -1) — 대소문자 구분함, 정규식 없음
- 필드값이 null이면 에러 발생 위험 — null.indexOf 호출. 데이터에 빈 값 있으면 방어 필요
- DataManager.filter() 위임 — 원본 데이터는 유지되고 표시만 좁혀짐
- clearFilter()로 필터 해제 가능
⚠️ 한글 초성 검색, 대소문자 무시, 정규식 매칭은 자동으로 안 됨. 필요하면 filter() 메서드를 오버라이드하거나 데이터를 미리 가공.
7. 이벤트 (Combobox와 거의 동일)
이벤트시그니처발생 시점
| select | (component, element, listItem, data, key, display, evt) | 항목 선택 시 |
| filterboxItemClick | (component, element, row, data, rowIndex, row, evt) | 리스트 아이템 클릭 (Combobox의 listItemClick에 해당) |
| filterboxItemContextmenu | 리스트 아이템 우클릭 | |
| beforePop / afterPop / hidePop | 팝업 표시 | |
| expand / collapse | 팝업 확장 | |
| focus / blur / click / change | 표준 |
⚠️ 이벤트 이름이 Combobox의 listItemClick이 아니라 filterboxItemClick 인 게 차이. 코드 옮길 때 주의.
8. 키보드 조작
키동작
| 타이핑 | isFilterRuntime:true면 자동 필터. 아니면 텍스트만 입력됨 |
| Enter | 필터 실행 + 팝업 열기 |
| ↓ (ArrowDown) | 팝업 열려 있으면 첫 항목 포커스 |
| Tab | 값이 비어 있으면 자동 클리어. 아니면 다음 필드로 |
| Esc | 팝업 닫기 |
| ↑↓ (팝업 내) | 항목 이동 |
| Enter (팝업 내) | 선택 확정 |
9. 메서드
Combobox의 메서드에 필터 관련 하나 추가:
값 관리
메서드설명
| getValue() | 선택된 값 (single/multi에 따라 문자열 또는 배열) |
| setValue(value) | 값 세팅 |
| getSelectedData() | 선택된 데이터 전체 객체 |
필터 (Filterbox 전용)
메서드설명
| filter(inputValue) | 프로그램적으로 필터 실행 |
데이터 (Combobox와 동일)
setData, getData, addData, insertData, modifyData, removeData, moveData, selectData, selectFirstData 등 전부 동일.
팝업 / 상태
메서드설명
| showFilterboxPop(evt) / hideFilterboxPop() | 팝업 제어 (Combobox는 showComboboxPop 등) |
| setDisabled(bool) / setReadOnly(bool) | 상태 |
| focus() / blur() | 포커스 |
10. 내부 구조
Combobox와 거의 동일하지만 readonly 속성이 제거되어 사용자가 필드에 직접 타이핑 가능:
<div elname="element" class="va-filterbox [size]..." tag-name="filterbox" field="true">
<div elname="fieldWrapper" class="field-wrapper" role="combobox">
<input elname="field" type="text" style="border:0px"> ← readonly 없음
<div elname="focusLine" class="focus-line"></div>
<div class="va-combobox-dropdown">▼</div>
</div>
<div elname="popDiv" class="menu-button-pop-div">
<div elname="pop" class="va-menu-pop" role="listbox"
style="position:absolute; display:none">
<div elname="popInner" class="combobox-pop-div">
<!-- 필터된 listItem만 표시 -->
</div>
</div>
</div>
</div>
핵심 차이: va_component.js:2921의 this.fieldElement.removeAttribute('readonly') — Combobox와 달리 readonly를 명시적으로 제거해 자유 입력 활성화.
11. Filterbox 계열 형제 컴포넌트
컴포넌트역할
| Va.Filterbox | 표준 필터박스 (이 문서) |
| Va.FilterboxRaw | 경량형 (기능 축소) |
| Va.FilterboxField | Filterbox + Field 래퍼 (라벨/검증) |
12. 언제 쓰나
Filterbox가 맞을 때
- 옵션이 50개 이상 — 스크롤보다 타이핑이 빠름
- 국가·도시·부서·제품 등 자동완성이 자연스러운 데이터
- 사용자가 대략적인 이름만 알고 있을 때
- 여러 필드에서 매칭 필요 (filterKeys로 이름/이메일/코드 모두)
다른 걸 쓸 때
- 옵션이 10개 이하 → Va.Combobox (스크롤로 충분)
- 라벨 필요 → Va.FilterboxField
- 다중 선택 + 칩 UI → Va.Tag
- 자유 텍스트 입력 (사전 정의 안 됨) → Va.Input
- 서버 검색 → 별도 구현 (dataMode 활용)
13. 흔한 조합 예시
// 국가 선택 (실시간 필터, display로만 검색)
{
tagName: 'filterbox',
filterKeys: ['display'],
isFilterRuntime: true,
data: countries // 200+개국
}
// 여러 필드 검색 (사원 조회)
{
tagName: 'filterbox',
filterKeys: ['name', 'employeeId', 'email'],
isFilterRuntime: true,
template: {
tagName: 'listItem',
layout: 'ds-flex fd-column',
tags: [
{ tagName: 'div', innerHTML: '{name}' },
{ tagName: 'div', innerHTML: '{email}', style: 'color:gray; font-size:12px' }
]
},
data: employees
}
// 대량 데이터, Enter로만 (부담 방지)
{
tagName: 'filterbox',
filterKeys: ['name'],
isFilterRuntime: false, // Enter 눌러야 필터
data: bigDataSet // 수만 건
}
// 다중 선택 + 필터 (Combobox 다중 + 검색)
{
tagName: 'filterbox',
multiSelect: true,
addCheckAll: true,
filterKeys: ['display'],
isFilterRuntime: true,
data: tags
}
// 자유 입력 허용 (데이터에 없는 값도 확정)
{
tagName: 'filterbox',
editable: true,
data: suggestions
}
14. 알아두면 좋을 주의사항
- filterKeys 필드 값이 null이면 크래시 — 소스가 item[filterKey].indexOf(...) 호출. 데이터에 null 값 방어 필요.
- 대소문자 구분 — indexOf 사용. filterKeys를 미리 소문자로 가공하거나 필터 로직 오버라이드.
- 한글 초성 검색 안 됨 — 별도 라이브러리로 데이터 가공 필요.
- isFilterRuntime: false가 기본 — Enter 눌러야 필터. 즉각 반응 원하면 명시적으로 true.
- filter()는 dataManager 필터 — 원본 데이터는 유지, 표시만 좁혀짐. clearFilter()로 복원.
- getValue()가 값을 반환하는 로직은 Combobox와 다를 수 있음 — editable: true일 때 필드 텍스트가 그대로 값으로 저장될 수 있음. 실제 확인 필요.
- 이벤트 이름이 filterboxItemClick — Combobox의 listItemClick이 아님.
- 필드가 편집 가능해서 값 상태와 표시가 불일치 가능 — 사용자가 텍스트를 지웠는데 실제 값(value)은 남아 있을 수 있음. Tab 시 자동 클리어 로직으로 일부 대응.
- rowHeight 기본이 30 — Combobox(34)보다 얇음. 시각적으로 정보 밀도 높음.
- 팝업이 hiddenArea로 이동 — 부모 stacking 영향 없음.
- 가상 스크롤 자동 — Combobox와 동일.
- 필터가 걸린 상태에서 CRUD — addData() 등 호출 시 필터 유지 여부 확인 필요. 예상과 다르면 clearFilter() 명시.
- 에디터 모드용 fakeData — VanillaFront Editor에서 미리보기 시 사용.
'컴포넌트 > 필드 컴포넌트' 카테고리의 다른 글
| DateTimePicker (일자시각선택) (0) | 2026.09.10 |
|---|---|
| DateField (날짜필드) (0) | 2026.09.10 |
| Tag (태그) (0) | 2026.09.10 |
| ComboboxField (콤보박스필드) (0) | 2026.09.10 |
| ColorField (색상필드) (0) | 2026.09.10 |