컴포넌트/필드 컴포넌트

NumberField (숫자필드)

VanillaFront 2026. 9. 10. 14:59

Va.NumberField — 라벨 + 숫자 입력 + 검증까지 감싼 폼 필드

Va.Number가 순수 숫자 입력이라면, Va.NumberField는 그 위에 라벨·필수 표시·검증 메시지·설명 텍스트를 얹은 "완성된 숫자 폼 필드" 입니다. Field 계열의 3형제(InputField, SearchField, NumberField)와 같은 아키텍처를 따르되, 내부에 Va.Number를 소유합니다.

  • 클래스: Va.NumberField  va_component.js:5494
  • short name: numberField
  • 상속: Va.Field (InputField·SearchField와 형제)
  • 내부 컴포넌트: Va.Number 인스턴스를 자식으로 소유 (fieldComponent)
  • isContainer: true
  • 베이스 CSS: va-field


1. 기본 사용

{
    tagName: 'numberField',
    label: '수량',
    value: 10,
    min: 0,
    max: 100,
    step: 1,
    required: true,
    onChange: 'onQtyChange'
}

라벨 · 필드 · 검증 영역이 자동 세팅되고, 내부 <input type="number">가 스피너까지 제공.


2. Field 3형제와의 위치

세 Field 컴포넌트가 완전히 같은 패턴으로 만들어져 있어 한 번에 정리:

Va.Field
   ├─ Va.InputField     ← 내부에 Va.Input      (text)
   ├─ Va.SearchField    ← 내부에 Va.Search     (search)
   ├─ Va.NumberField    ← 내부에 Va.Number     (number)    ← 이 문서
   ├─ Va.TextareaField
   ├─ Va.ComboboxField
   └─ ...

세 개 모두:

  • 라벨/검증/설명 영역 = Field 베이스가 제공
  • 실제 입력창 = 내부 PureField 계열 인스턴스가 담당
  • 옵션 spread + _syncProperties 패턴 동일

차이는 딱 세 가지:

  1. 내부에 어떤 PureField를 생성하는가 (Va.Number)
  2. 세부 커스터마이즈 옵션 키 (number)
  3. Number 전용 속성 추가 (min / max / step)

3. Va.Number / Va.InputField와의 차이

항목Va.NumberVa.NumberFieldVa.InputField

라벨
검증 메시지
설명 텍스트
info 툴팁
input type number 고정 number 고정 text 기본
min / max / step ✓ (전용 속성) ✕ (input 옵션으로만)
textAlign 기본 'right' 'right' 왼쪽
브라우저 스피너

4. 주요 속성

Number 전용 속성 (Field 위에서도 유효)

속성기본값설명

min 최솟값
max 최댓값
step (내부 Number 기본 1) 스피너 증감 단위

주목: 이 세 개가 Field 자체의 properties에 추가되어 있습니다 (va_component.js:5500). InputField/SearchField와의 차이. 그래서 setOption()이 인식하고 _syncProperties()로 내부 Number에도 자동 반영됩니다.

⚠️ decimalPlaces는 NumberField의 명시 속성이 아님 — 하지만 number 옵션 통해서 넘길 수는 있습니다 (아래 참조).

라벨 관련 (Field 상속)

속성기본값설명

label 라벨 텍스트 또는 옵션 객체
labelPosition 'top' top / bottom / left / right
labelWidth 자동 라벨 영역 폭
labelAlign 라벨 정렬
noLabel false 라벨 영역 숨김
infoButton 라벨 옆 info 아이콘 (툴팁)
required false 필수 표시

필드 관련 (Number로 위임)

속성설명

value 필드 값
placeholder 플레이스홀더
readonly / disabled 상태
textAlign 정렬 — 기본 'right' (숫자 관행)
size / appearance / shape 시각 스타일
masking 마스킹 (거의 안 씀)
valueType 값 타입 힌트

검증

속성설명

validation {state, size, message} 객체
validationState success / warning / error
validationMessage 메시지 텍스트
validationSize 메시지 크기

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

{
    tagName: 'numberField',
    label: '평점',
    min: 0,
    max: 5,
    step: 0.1,
    number: {                       // ← 내부 Number에 직접 전달
        decimalPlaces: 1,
        autocomplete: 'off'
    }
}

number 객체는 va_component.js:5524에서 내부 Va.Number 생성 시 spread됩니다. 특히 decimalPlaces는 이 통로로 넘겨야 반영됩니다 (Field 자체 속성엔 선언 안 되어 있음).

각 Field 계열의 옵션 키가 다릅니다 — InputField는 input, SearchField는 search, NumberField는 number.


5. 이벤트 (Field 상속)

Input/Search Field와 완전히 동일:

이벤트시그니처발생 시점

change (component, element, evt) 값 변경 확정. 발생 시 검증 자동 리셋
focus / blur (component, element, evt) blur 200ms debounce
click (component, element, evt) 필드 클릭
keydown (component, element, keyCode, evt) 검증 자동 리셋
keyup (component, element, evt)
keypress (component, element, evt)
contextmenu / mousedown 표준  

6. 메서드 (Field 상속)

InputField·SearchField와 완전히 동일:

메서드설명

getValue() 내부 Number의 getValue() 위임 (문자열 반환 — 계산엔 Number() 변환 필요)
setValue(value) 값 세팅 + 검증 자동 리셋 (내부 Number가 decimalPlaces 적용)

상태

메서드설명

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

검증

메서드설명

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

포커스

메서드설명

focus() / blur() 내부 Number에 위임

주의: setMin / setMax / setStep 같은 편의 setter는 없습니다. 값 변경이 필요하면 component.min = ...; component.update()로 직접.


7. 내부 구조

<div elname="element" class="va-field va-input [vertical|horizontal] [disabled]" 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.Number
        <div class="field-wrapper">
          <input type="number" step="1" min="0" max="100" ...>
          <div class="focus-line"></div>
        </div>
      </div>
    </div>
  </div>
  <div elname="validationDiv" style="display:none">
    <div class="va-validation">...</div>
  </div>
</div>

InputField/SearchField와 구조 동일, 안쪽 input의 type="number" + step/min/max 속성만 다름.


8. 언제 쓰나

NumberField가 맞을 때

  • 폼 안 숫자 입력 필드 (수량·나이·평점·금액)
  • 라벨과 함께 필수 표시·검증 메시지가 필요할 때
  • 범위 제한(min/max)이 명확한 값
  • 소수점 자릿수 강제(number.decimalPlaces)가 필요한 값

다른 걸 쓸 때

  • 라벨 없는 인라인 숫자 입력 → Va.Number
  • ±버튼이 좌우에 붙은 형태 → Va.NumberWithButtonField
  • 금액에 콤마 포맷 → Va.InputField + input.numberComma:true
  • 텍스트+숫자 혼합 (전화번호, 신용카드 등) → Va.InputField + masking

9. 흔한 조합 예시

// 수량
{
    tagName: 'numberField',
    label: '수량',
    min: 0,
    max: 999,
    step: 1,
    value: 1,
    required: true
}

// 평점 (0~5, 소수 첫째)
{
    tagName: 'numberField',
    label: '평점',
    min: 0,
    max: 5,
    step: 0.1,
    number: { decimalPlaces: 1 },
    value: 3.5
}

// 금액 (1000원 단위 스피너)
{
    tagName: 'numberField',
    label: '금액',
    min: 0,
    step: 1000,
    value: 10000,
    textAlign: 'right'
}

// 환율 (소수 넷째)
{
    tagName: 'numberField',
    label: '환율',
    step: 0.0001,
    number: { decimalPlaces: 4 },
    value: 1300.1234
}

// 나이 (info 툴팁 포함)
{
    tagName: 'numberField',
    label: '나이',
    min: 0,
    max: 150,
    infoButton: {
        tooltip: '만 나이 기준으로 입력하세요'
    }
}

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

  1. getValue()는 문자열 — 계산엔 Number(component.getValue()) 변환 필수.
  2. min/max는 키보드 직접 입력 못 막음 — 정확한 범위 강제는 change 콜백에서 clamp하거나 setValidation('error', ...)으로 알림.
  3. decimalPlaces는 number 옵션으로만 — Field 자체 속성엔 없음. {number: {decimalPlaces: 2}} 형태로 전달.
  4. type 변경 불가  'number' 고정. text로 쓰려면 InputField 사용.
  5. numberComma 미지원 — 금액 콤마 필요하면 InputField + numberComma 조합.
  6. 초기 value가 0 — 빈 값 시작 원하면 value: '' 명시 (내부 Number의 기본값).
  7. textAlign 기본 'right' — 숫자 관행. 왼쪽 정렬 필요하면 명시.
  8. change/keydown 시 검증 자동 리셋 — 사용자가 값을 수정하기 시작하면 이전 에러가 사라짐.
  9. 브라우저 스피너 UX — 스피너 폭이 필드 오른쪽을 잡아먹음. 얇은 필드에선 CSS로 숨기는 게 나을 수 있음.
  10. decimalPlaces 실시간 반올림 UX 주의 — 사용자가 소수 입력 중일 때 값이 튀는 느낌이 있음 (내부 Number의 keyup 동작).
  11. 옵션 키가 number — InputField의 input, SearchField의 search와 헷갈리지 말 것.
  12. 필수 검증 자동화는 없음  required: true는 라벨 별표만 표시. 실제 값 존재 검증은 콜백에서 setValidation() 호출로 처리.

'컴포넌트 > 필드 컴포넌트' 카테고리의 다른 글

ColorField (색상필드)  (0) 2026.09.10
ColorPicker(색상선택)  (0) 2026.09.10
Number (숫자)  (0) 2026.09.10
SearchField (검색필드)  (0) 2026.09.10
Search (검색)  (0) 2026.09.10