카테고리 없음

TagField (태그필드)

VanillaFront 2026. 9. 10. 15:25

Va.TagField — 라벨 + 태그(칩) 입력 + 검증까지 감싼 완성 폼 필드

Va.Tag가 순수 태그 칩 입력이라면, Va.TagField는 그 위에 라벨·필수 표시·검증 메시지·설명 텍스트 + 부모-자식 필드 바인딩을 얹은 완성 폼 필드입니다. ComboboxField와 완전히 같은 아키텍처 패턴을 따르되, 내부에 Va.Combobox 대신 Va.Tag 를 소유합니다.

  • 클래스: Va.TagField  va_tag.js:1407
  • short name: tagField
  • 상속: Va.Field (ComboboxField·InputField 등과 형제)
  • 파일: va_tag.js (import 필요)
  • 내부 컴포넌트: Va.Tag 인스턴스 (fieldComponent)
  • isContainer: true
  • 베이스 CSS: va-tag-field


1. 기본 사용

import '../../lib/va_tag.js';  // ← 필수 (Tag + TagField 둘 다 이 파일에)

// config 안에서
{
    tagName: 'tagField',
    label: '기술 스택',
    data: [
        { key: 'js', display: 'JavaScript' },
        { key: 'ts', display: 'TypeScript' },
        { key: 'py', display: 'Python' },
        { key: 'go', display: 'Go' }
    ],
    value: ['js', 'ts'],
    required: true,
    onSelect: 'onTagChange'
}

라벨 + 검증 + 팝업 드롭다운 + 칩 UI가 한 번에 세팅됩니다.


2. Field 계열에서의 위치 — ComboboxField의 판박이

TagField는 사실상 ComboboxField의 소스를 복사해서 내부만 Combobox → Tag로 바꾼 것입니다. 옵션 구성, 이벤트 재발화, 메서드 위임 패턴이 거의 100% 동일해요.

Va.Field
   ├─ Va.InputField        ← Va.Input
   ├─ Va.SearchField       ← Va.Search
   ├─ Va.NumberField       ← Va.Number
   ├─ Va.ComboboxField     ← Va.Combobox
   ├─ Va.FilterboxField    ← Va.Filterbox
   ├─ Va.TagField          ← Va.Tag              ← 이 문서
   └─ ...

차이는 하나: 내부에 어떤 컴포넌트가 들어가느냐. 그래서 옵션·메서드·이벤트 세트가 ComboboxField와 거의 같은 걸 보게 됩니다.


3. Va.Tag / Va.ComboboxField와의 차이

항목Va.TagVa.TagFieldVa.ComboboxField

라벨
검증 메시지
info 툴팁
선택 표시 방식 칩 (chip) 칩 (chip) — Tag 위임 텍스트 콤마 나열
개별 삭제 X 버튼
multiSelect 기본 true true false
bindParams (부모 바인딩)
bindCallbackKeys (자식 자동 채움)
파일 va_tag.js va_tag.js va_component.js

한 줄 요약: "다중 선택 + 칩 UI + 라벨 + 검증"이 필요한 폼 필드.


4. 주요 속성 — Tag 옵션 + Field 옵션 + 바인딩 옵션

ComboboxField와 거의 동일합니다.

데이터 관련

속성기본값설명

data 항목 배열
fakeData 에디터 미리보기
key 'key' 값 필드명
display 'display' 표시 필드명
displayType 'display' key / display / both  칩 안 텍스트 형태
template 자동 생성 팝업 항목 렌더 템플릿 (칩 자체 아님)
dataMode 'data' 데이터 소스 모드

선택 동작

속성기본값설명

value 선택된 키 배열
multiSelect true 기본이 true
addCheckAll "전체" 체크
clickToSelect true 클릭 선택
getValueType 'string'이면 getValue()가 "'a','b','c'" 형태
fromValue / toValue 범위 옵션

팝업

속성기본값설명

expanded false 팝업 초기 상태
popWidth 자동 팝업 폭
popMaxHeight '400px' 팝업 최대 높이

라벨 (Field 상속)

속성설명

label 라벨 텍스트 또는 객체
labelPosition top / bottom / left / right
labelWidth 라벨 폭
noLabel 라벨 숨김
infoButton info 아이콘
required 필수 표시

검증

속성설명

validation {state, size, message}
validationState success / warning / error
validationMessage 메시지

바인딩 (ComboboxField와 동일)

속성설명

bindParams 팝업 열기 전 부모 필드 값 자동 수집
bindRequired 바인딩 필드 비면 팝업 안 열림
bindCallbackKeys 선택 후 다른 필드에 값 자동 세팅
bindCallbackClearKeys 선택 후 다른 필드 자동 비우기
commonCode 공통 코드 마스터
commonBlankKey "빈 값" 옵션 key
dynamicCode 동적 코드 (파라미터 기반)

세부 커스터마이즈 (tag 옵션 키)

{
    tagName: 'tagField',
    label: '태그',
    tag: {                        // ← 내부 Tag에 직접 전달
        rowHeight: 40,
        pageSize: 50
    }
}

각 Field 계열 옵션 키:

  • InputField → input
  • SearchField → search
  • NumberField → number
  • ColorField → colorPicker
  • ComboboxField → combobox
  • TagField → tag

5. 이벤트

Tag의 이벤트를 모두 재발화:

이벤트시그니처발생 시점

select (component, element, listItem, data, key, display, evt) 팝업에서 선택 시 또는 칩 X로 제거 시
beforePop / afterPop 팝업 표시  
hidePop 팝업 숨김  
expand / collapse 팝업 확장  
focus / blur 표준  
change / click / keydown / keyup Field 표준 (검증 자동 리셋)  

⚠️ X 클릭 시 select 이벤트는 인자 개수가 짧음 — Tag 자체의 동작 그대로. 팝업 선택 시 7개, X 클릭 시 3개. 콜백 방어 필요.


6. 메서드 — Tag의 모든 메서드에 대한 위임

메서드설명

getValue() 선택된 키 배열 반환. getValueType: 'string'이면 문자열
setValue(value) 배열 또는 단일 값. null/"" 넘기면 초기화
getDisplay() / getDisplayAsText() 표시 텍스트

데이터 (Tag 위임)

메서드설명

setData(data) 데이터 교체 (선택된 태그 초기화됨)
getData() 팝업 리스트 데이터 (선택 제외)
getSelectedData() 선택된 전체 객체 배열
addData(data) / insertData(data, baseData) 추가/삽입
modifyData(data, cls) 수정
removeData(data) / removeDataByKey(key) 제거
moveData(data, beforeData) 이동
select(data) 프로그램적 선택
selectFirstData(eventOccur) 첫 항목 자동 선택
focusFirstData(eventOccur) selectFirstData 별칭
applyData() 데이터 반영
getDataById(vaDataId) 내부 ID로 조회
getDataByListItem(listItem) / getListItemByData(data) 상호 조회

상태 (Field 상속)

메서드설명

setDisabled(bool) / getDisabled() 비활성화
setReadOnly(bool) / setReadonly(bool) 읽기 전용
setLabel(label) 라벨 변경
setPlaceholder(text) 플레이스홀더
setSize(size) 크기

검증

메서드설명

setValidation(state, message) 검증 표시 + aria 자동
clearValidation() 검증 해제

바인딩

메서드설명

getBindParams(component) 부모 필드 값 수집 (Tag 위임)
setCallbackKeys(component, data) 자식 필드 자동 채움

포커스

메서드설명

focus() / blur() 내부 Tag의 fieldElement에 위임

7. 내부 구조

<div elname="element" class="va-field va-tag-field [vertical|horizontal]" field="true">
  <div elname="inner" class="field-inner">
    <div elname="labelDiv" class="label-div">
      <label cpname="label">기술 스택 <span class="required">*</span></label>
    </div>
    <div elname="comment" class="field-comment"></div>
    <div elname="fieldDiv" class="field-div">
      <div cpname="field" class="va-input">              ← 내부 Va.Tag
        <div class="field-wrapper">
          <div elname="field" tabindex="-1"
               style="display:flex; flex-wrap:wrap; gap:3px">
            <span class="va-tag-item">JavaScript ✕</span>
            <span class="va-tag-item">TypeScript ✕</span>
          </div>
          <div class="focus-line"></div>
          <div class="va-combobox-dropdown">▼</div>
        </div>
        <!-- 팝업은 hiddenArea로 이동됨 -->
      </div>
    </div>
  </div>
  <div elname="validationDiv" style="display:none">
    <div class="va-validation">...</div>
  </div>
</div>

8. 언제 쓰나

TagField가 맞을 때

  • 폼 안 다중 태그 선택 (게시글 카테고리 여러 개, 참여자 목록, 관심 분야)
  • 개별 삭제 UX가 필요한 폼 필드
  • 라벨·필수·검증 메시지가 필요한 태그 UI
  • Gmail·GitHub 스타일 라벨 지정

다른 걸 쓸 때

  • 라벨 없는 인라인 → Va.Tag
  • 콤마 텍스트로 충분 (칩 안 필요) → Va.ComboboxField + multiSelect: true
  • 텍스트 필터링 강화 → Va.FilterboxField
  • 단일 선택 → Va.ComboboxField

9. 흔한 조합 예시

// 표준 사용
{
    tagName: 'tagField',
    label: '카테고리',
    data: [
        { key: 'work', display: '업무' },
        { key: 'personal', display: '개인' },
        { key: 'urgent', display: '긴급' }
    ],
    value: ['work'],
    required: true
}

// 서버 전송용 문자열 반환
{
    tagName: 'tagField',
    label: '권한',
    data: [...],
    getValueType: 'string',       // "'admin','user','guest'" 형태
    onSelect: 'onPermissionChange'
}

// 좌측 라벨 + 필수
{
    tagName: 'tagField',
    label: '참여자',
    labelPosition: 'left',
    labelWidth: 100,
    required: true,
    data: [...]
}

// 커스텀 팝업 템플릿 (아이콘 + 설명)
{
    tagName: 'tagField',
    label: '기술',
    template: {
        tagName: 'listItem',
        layout: 'ds-flex fd-row ai-center gap-s',
        tags: [
            { tagName: 'i', innerHTML: '{icon}' },
            { tagName: 'span', innerHTML: '{display}' },
            { tagName: 'span', innerHTML: '{level}', style: 'color:gray' }
        ]
    },
    data: [
        { key: 'js', display: 'JavaScript', icon: '🟨', level: '숙련' }
    ]
}

// 부모-자식 바인딩 (지역에 따른 지점 태그)
{
    tagName: 'comboboxField',
    label: '지역',
    ref: 'region',
    data: [...]
},
{
    tagName: 'tagField',
    label: '지점 (복수 선택)',
    bindParams: { regionCode: 'region' },
    bindRequired: true,
    dynamicCode: 'BRANCH_BY_REGION'
}

// 팝업 폭 크게
{
    tagName: 'tagField',
    label: '관심 주제',
    popWidth: 400,
    popMaxHeight: '500px',
    data: [...]
}

10. 알아두면 좋을 주의사항

  1. va_tag.js import 필수 — Tag와 TagField가 같이 들어 있음.
  2. getValue() 반환은 배열 또는 문자열  getValueType 옵션에 따라. 서버 전송 시 확인.
  3. select 이벤트 인자 개수 상황에 따라 다름 — 팝업 선택 7개, 칩 X 클릭 3개. 방어 코드 필요.
  4. 자유 태그 생성 불가 — 사전 정의된 data에서만 선택. 사용자 타이핑으로 새 태그 만드는 기능 없음.
  5. autoSetFieldValue: false 강제 — Tag 로직에 맞춤.
  6. multiSelect: true가 기본 — TagField를 single로 쓸 일이 별로 없지만, 굳이 하려면 명시 지정.
  7. 팝업이 hiddenArea로 이동 — 부모 overflow/z-index 영향 없음.
  8. 바인딩 이벤트 자동 등록  bindParams/bindCallbackKeys/bindCallbackClearKeys 중 하나라도 있으면 자동. ComboboxField는 명시적 등록 코드가 있는데 TagField에는 없음 → 바인딩 옵션이 있어도 자동 트리거 이벤트 리스너 코드는 빠져 있음. Combobox의 내부 로직에 의존.
  9. addCheckAll은 실제로 동작할지 확인 필요 — TagField의 옵션 목록엔 있으나 Tag의 template 자동 생성 로직에서 checkbox를 만들지 여부가 미묘. 데모에서 검증 권장.
  10. 템플릿 자동 생성 — 지정 안 하면 display 필드만 있는 심플 리스트. TagField는 Tag와 달리 checkbox 자동 포함 없음(이 자체가 Tag의 X 클릭으로 대체됨).
  11. _hiddenRootElement가 popElement — 팝업 상태머신 참여.
  12. 옵션 키가 tag — 다른 Field 형제들과 헷갈리지 말 것.
  13. getBindParams / setCallbackKeys 위임 메서드 존재 — 하지만 setCallbackKeys는 자기 자신을 재귀 호출하는 구현 실수가 있음 (va_tag.js:1411-1413) — 호출 시 스택 오버플로 위험. 필요 시 fieldComponent.setCallbackKeys() 직접 호출.
  14. focus()는 fieldElement에 포커스 — Tag의 field는 tabindex=-1이라 실질적 효과 미미. 팝업 열기 원하면 showPop() 직접.

11. TagField가 없어도 되는가?

기술적으로는 Va.Tag만으로도 라벨을 직접 붙여 폼을 만들 수 있습니다. 하지만:

  • 검증 통합: setValidation(), clearValidation()으로 표준 폼 검증 UX 자동
  • 폼 통일성: 다른 Field 계열과 라벨/에러 위치·간격이 자동 통일
  • ARIA 접근성: 라벨-필드 연결이 자동
  • 바인딩 옵션: bindParams, bindCallbackKeys 등 폼 필드 간 연동 문법 사용

이걸 손으로 다시 짜는 것보다 TagField 쓰는 게 압도적으로 편합니다.