컴포넌트/필드 컴포넌트

YearPicker (연도선택)

VanillaFront 2026. 9. 11. 14:10

Va.YearPicker — 년도만 선택하는 캘린더 팝업

Va.DatePicker의 축소판. 년도 하나만 선택하는 데 특화된 컴포넌트입니다. 팝업엔 10년 단위 그리드가 표시되고, 화살표로 10년씩 이동합니다. 회계연도·연간 통계·설립연도 같은 필드에 적합해요.

  • 클래스: Va.YearPicker  va_component.js:6383
  • short name: yearPicker
  • 상속: Va.PureField (DatePicker와 형제)
  • isContainer: true
  • 베이스 CSS: va-yearpicker (팝업 va-menu-pop, calendar-inner)

 


1. 기본 사용

{
    tagName: 'yearPicker',
    value: '2024',
    onSelect: 'onYearChange'
}
  • 화면 표시: 2024
  • 팝업: 년도 10개 격자 (예: 2020~2029년)
  • 화살표: ← 10년 뒤로 / → 10년 앞으로

2. Va.DatePicker / Va.MonthPicker와의 차이

항목Va.YearPickerVa.MonthPickerVa.DatePicker

입력 대상 년도만 (4자리) 년-월 (6자리) 년-월-일 (8자리)
저장 값 '2024' '202412' '20241225'
팝업 UI 10년 격자 12개월 격자 일 단위 캘린더
화살표 이동 10년씩 1년씩 1개월씩
마스킹 없음 ____-__ ____-__-__
popWidth 기본 240 (유사) 260

한 줄 요약: "년도 4자리만 필요한 상황을 위한 가장 가벼운 캘린더 필드."


3. 주요 속성

팝업

속성기본값설명

popWidth 240 팝업 폭
expanded false 팝업 초기 상태

날짜 포맷 (선언은 있으나 실질 영향 미미)

속성설명

dateFormat properties에 있으나 년도만이라 사용처가 제한적
dateSeperator 마찬가지
valueDateFormat / valueDateSeperator 저장 형식 조정용 (실제 로직에 반영 여부 확인 필요)

⚠️ DatePicker의 형식 옵션들이 그대로 선언되어 있지만, 년도 하나만 다루기 때문에 실질 효과는 거의 없습니다. setValue/getValue가 값 그대로 통과시키는 단순 구현.

PureField 상속

value, placeholder, readonly, disabled, size, appearance, stopPropagation 등 표준.


4. 이벤트

이벤트시그니처발생 시점

select (component, element, value, null) 년도 클릭 시. value는 선택된 년도 문자열
beforePop / afterPop / hidePop 팝업 표시/숨김  
expand / collapse 팝업 확장/축소  
focus / blur 표준  

5. 메서드

값 관리 — 매우 단순

메서드설명

setValue(value) value를 그대로 필드에 세팅. 변환 없음
getValue() 필드 값 그대로 반환 (fieldElement.value)

DatePicker처럼 포맷 변환 로직이 없어서 매우 심플합니다.

팝업 제어

메서드설명

showYearPickerPop(evt) / hideYearPickerPop() 팝업 강제 열기/닫기
showPop() / expand() drawCalendar() 호출 (레거시 별칭)
hidePop() / collapse() 팝업 숨김
drawCalendar(value) 팝업 내부 년도 격자 렌더링

상태 (PureField 상속)

메서드설명

setDisabled(bool) / setReadOnly(bool) 상태
focus() / blur() 포커스

6. 팝업 UI 구조

drawCalendar()가 렌더링:

┌─────────────────────────────┐
│  ←   2020~2029년   →        │  ← 헤더 (10년 범위 표시)
├─────────────────────────────┤
│  2020    2021               │
│  2022    2023               │
│  2024    2025               │  ← 2×5 격자 (10개 년도)
│  2026    2027               │
│  2028    2029               │
└─────────────────────────────┘
  • 10년씩 이동 (← /  버튼)
  • grid 2열 5행 (2×5 = 10개 버튼)
  • 각 년도가 버튼 — 클릭 시 select 이벤트 발생 + 팝업 닫힘

내부에서 Math.floor(value / 10) * 10으로 10년 단위 시작 년도를 계산합니다 (va_component.js:6571).


7. 내부 구조

<div elname="element" class="va-yearpicker [size]..." tag-name="yearPicker" field="true">
  <div elname="fieldWrapper" class="field-wrapper">
    <input elname="field" type="text" style="border:0px">
    <div elname="focusLine" class="focus-line"></div>
    <div elname="calendarIconWrapper">
      <span elname="calendarIcon" class="icon menu ico_calender_ltr">📅</span>
    </div>
  </div>
  <div elname="popDiv" class="menu-button-pop-div">
    <div elname="pop" class="va-menu-pop" style="position:absolute; display:none">
      <div elname="popInner" class="calendar-inner">
        <div class="date-picker-pop-header">
          ← 2020~2029년 →
        </div>
        <div elname="popContent" style="display:grid; grid-template-columns:1fr 1fr; gap:10px">
          <!-- 10개 년도 버튼 -->
        </div>
      </div>
    </div>
  </div>
</div>

8. 팝업 상태머신 연동

프레임워크 공용 팝업 상태머신 참여:

  • Va.addAutoHide(this.popElement) — 외부 클릭 시 자동 닫힘
  • Va.hideOtherComponents(this) — 다른 팝업 자동 닫음
  • getHiddenAreaElement()로 팝업 이동 → 부모 stacking 회피
  • 뷰포트 넘침 시 위로 자동 뒤집기

DatePicker와 동일한 팝업 인프라를 그대로 씁니다.


9. 언제 쓰나

YearPicker가 맞을 때

  • 회계연도 선택 (2024년도 결산 등)
  • 연도별 통계 필터 (2020~2024 실적 조회)
  • 설립연도·졸업연도 등 년도만 필요한 개인정보
  • 연간 리포트의 년도 파라미터
  • 월·일이 무의미한 상황

다른 걸 쓸 때

  • 년-월 필요 → Va.MonthPicker
  • 년-월-일 필요 → Va.DatePicker
  • 시간까지 필요 → Va.DateTimePicker
  • 시작-종료 년도 → 두 YearPicker 조합
  • 콤보 형태 (드롭다운) → Va.Combobox에 년도 배열 넣기

10. 흔한 조합 예시

// 표준 사용
{
    tagName: 'yearPicker',
    value: '2024',
    onSelect: 'onYearChange'
}

// 초기 값 없이 (오늘 기준으로 팝업 열림)
{
    tagName: 'yearPicker',
    placeholder: '년도 선택'
}

// 좁은 팝업 (기본 240보다)
{
    tagName: 'yearPicker',
    popWidth: 180,
    value: '2024'
}

// 읽기 전용
{
    tagName: 'yearPicker',
    value: '2024',
    readonly: true
}

// 라벨과 함께 → YearField 사용 검토
{
    tagName: 'yearField',      // 있다면
    label: '회계연도',
    value: '2024',
    required: true
}

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

  1. value는 문자열  '2024' 형태. 숫자 넘겨도 대체로 동작하지만 문자열이 안전.
  2. setValue()는 값 그대로 통과 — DatePicker와 달리 포맷 변환 없음. 잘못된 값도 그대로 필드에 표시됨.
  3. getValue()는 필드값 그대로 반환 — 사용자가 필드에 직접 타이핑한 값이 그대로 나옴. 검증 없음.
  4. 필드 타이핑 자유 — 마스킹 없어서 아무 문자나 입력 가능. 별도 검증 필요.
  5. dateFormat 등 포맷 옵션 실효 미미 — properties에 있지만 년도 하나만 다뤄 실제 로직 반영이 제한적.
  6. 10년 격자만 지원 — 5년, 20년 격자 옵션 없음.
  7. popWidth 기본 240 — DatePicker(260)보다 작음. 격자가 2열이라 좁아도 됨.
  8. 팝업 상태머신 참여 — 다른 팝업과 자동 상호 배타.
  9. 초기값 없으면 오늘 년도 기준  drawCalendar()가 Va.Util.getNowYear()로 fallback.
  10. select 이벤트 4번째 인자가 null — DatePicker와 시그니처 유사. 실무엔 무관.
  11. 에디터 아이콘 뷰포트 벗어남 처리  getBoundingClientRect().bottom이 뷰포트 넘치면 위로 뒤집기. 자동 처리됨.

12. 실전 예 — 연간 리포트 필터

class AnnualReport extends Va.View {
    mounted() {
        // 오늘 년도로 초기화
        const currentYear = String(new Date().getFullYear());
        this.getRef('year').setValue(currentYear);
        this.loadReport(currentYear);
    }

    onYearChange(picker, el, value, _) {
        this.loadReport(value);
    }

    loadReport(year) {
        ReportService.getAnnual(this, { year }, (view, ok, res) => {
            if (ok) view.getRef('grid').setData(res.data.list);
        });
    }

    config() {
        return {
            tagName: 'page',
            tags: [{
                tagName: 'panel',
                tags: [
                    { tagName: 'h2', innerHTML: '연간 실적 리포트' },
                    {
                        tagName: 'div',
                        layout: 'ds-flex fd-row ai-center gap-s',
                        tags: [
                            { tagName: 'label', innerHTML: '년도:' },
                            {
                                tagName: 'yearPicker',
                                ref: 'year',
                                onSelect: 'onYearChange',
                                style: { width: '120px' }
                            }
                        ]
                    },
                    {
                        tagName: 'grid',
                        ref: 'grid',
                        columns: [
                            { key: 'month',   title: '월',   width: 60 },
                            { key: 'revenue', title: '매출', fillRatio: 1 },
                            { key: 'cost',    title: '원가', fillRatio: 1 }
                        ]
                    }
                ]
            }]
        };
    }
}

흐름:

  1. mounted()에서 현재 년도로 초기화 + 리포트 로드
  2. 사용자가 팝업에서 다른 년도 선택 → onYearChange → 리포트 재조회
  3. 그리드가 새 데이터로 갱신

13. YearField가 필요하면

라벨·검증까지 필요한 폼 필드로 쓰려면 Va.YearField (Field 계열 래퍼)를 확인해 보세요. 다른 Field 형제들과 같은 패턴으로:

{
    tagName: 'yearField',
    label: '회계연도',
    value: '2024',
    required: true,
    validation: { state: 'success' }
}

⚠️ 프로젝트 내 실제 존재 여부는 확인 후 사용. Field 형제 중 dateField / dateTimeField / monthField 등의 명명 관행에 맞춰 yearField가 있을 가능성이 높습니다.

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

YearField (연도필드)  (0) 2026.09.11
DateTimeField (일시필드)  (0) 2026.09.11
DateTimePicker (일자시각선택)  (0) 2026.09.10
DateField (날짜필드)  (0) 2026.09.10
Filterbox (필터박스)  (0) 2026.09.10