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. 알아두면 좋을 주의사항
- value는 문자열 — '2024' 형태. 숫자 넘겨도 대체로 동작하지만 문자열이 안전.
- setValue()는 값 그대로 통과 — DatePicker와 달리 포맷 변환 없음. 잘못된 값도 그대로 필드에 표시됨.
- getValue()는 필드값 그대로 반환 — 사용자가 필드에 직접 타이핑한 값이 그대로 나옴. 검증 없음.
- 필드 타이핑 자유 — 마스킹 없어서 아무 문자나 입력 가능. 별도 검증 필요.
- dateFormat 등 포맷 옵션 실효 미미 — properties에 있지만 년도 하나만 다뤄 실제 로직 반영이 제한적.
- 10년 격자만 지원 — 5년, 20년 격자 옵션 없음.
- popWidth 기본 240 — DatePicker(260)보다 작음. 격자가 2열이라 좁아도 됨.
- 팝업 상태머신 참여 — 다른 팝업과 자동 상호 배타.
- 초기값 없으면 오늘 년도 기준 — drawCalendar()가 Va.Util.getNowYear()로 fallback.
- select 이벤트 4번째 인자가 null — DatePicker와 시그니처 유사. 실무엔 무관.
- 에디터 아이콘 뷰포트 벗어남 처리 — 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 }
]
}
]
}]
};
}
}
흐름:
- mounted()에서 현재 년도로 초기화 + 리포트 로드
- 사용자가 팝업에서 다른 년도 선택 → onYearChange → 리포트 재조회
- 그리드가 새 데이터로 갱신
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 |