Vue Component 개발— Datepicker

Seungwon Go
ReturnValues
Published in
10 min readFeb 23, 2018

Bootstrap Datepicker를 vue용 component로 구현하는 방법에 대해 알아 보겠다.

사용된 plugin : http://bootstrap-datepicker.readthedocs.io/

어플리케이션에서 사용되는 날짜 선택 타입 3가지로 구분된다.

  1. 년도 선택
  2. 월 선택
  3. 날짜 선택

하나의 Component로 위의 3가지 타입을 다 처리할 수 있지만, 각각을 별도의 Component로 개발해 놓으면 개발자 입장에서 사용하기 훨씬 편하고 관리하기도 편해진다.

먼저 개발된 YearPicker에 해당하는 Component 소스를 보자.

YearPicker

<template>
<div class="input-group date" style="width:100px;">
<input type="text" class="form-control" v-model="year" />
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</template>
<script>
export default {
name: 'year-picker',
props: {
year: String
},
mounted: function() {
var that = this;
$(this.$el).datepicker({
'autoclose':true,
'minViewMode':2,
'maxViewMode':2,
'format':'yyyy'
}).on('changeDate', function(e){
that.$emit('change',String(e.date.getFullYear()));
});
},
updated: function(){
$(this.$el).datepicker('update', this.year);
}
}
</script>

props

props로는 year를 1개를 사용한다. 해당 프로퍼티는 YearPicker를 호출하는 상위 컴포넌트에서 정의된 data를 상속받기 위해 사용된다.

props: {
year: String
}

mounted

플러그인으로 bootstrap-datepicker를 이용하고 있기 때문에, 컴포넌트가 mounted되면 bootstrap-datepicker의 객체 선언 메소드를 호출하여, template에서 선언된 Html Element가 Datepicker로 동작할 수 있도록 선언해 준다.

이때 옵션은 년도를 선택하는 Datepicker를 개발할 것이므로, minViewMode와 maxViewMode는 2, format은 yyyy로 설정한다.

mounted: function() {
var that = this;
$(this.$el).datepicker({
'autoclose':true,
'minViewMode':2,
'maxViewMode':2,
'format':'yyyy'
}).on('changeDate', function(e){
that.$emit('change',String(e.date.getFullYear()));
});
}

datepicker 선언시 Event를 바인딩 하였는데, .on(‘changeDate’) 이 부분은 좀 있다가 부연 설명을 하겠지만, 우리가 사용하고 있는 플러그인인 bootstrap-datepicker의 경우 사용자의 액션으로 날짜가 변경되어도 바인딩된 모델에서 인식하지 못하기 때문에, 날짜가 변경이 되었을때 변경된 값을 parent로 전달하기 위해서 사용된다.

YearPicker 사용

자 이제 실제로 YearPicker 컴포넌트를 호출하는 Vue 소스에서는 어떻게 이용되는지 살펴보자.

<template>
<year-picker
:year="year_from"
@change="changeFromYear"
/>
~
<year-picker
:year="year_to"
@change="changeFromYear"
/>
</template>
<script>
import YearPicker from '@/components/YearPicker';
export default {
name: 'year-picker-example',
components: {
YearPicker
},
data() {
return {
year_from : '',
year_to : ''
}
},
mounted() {
var d = new Date();
var toYear = d.getFullYear();
var fromYear = toYear - 10;
this.year_from = String(fromYear); //10년 전 년도
this.year_to = String(toYear); //현재 년도

},
methods: {
changeFromYear(year) {
this.year_from = year;
},
changeToYear(year) {
this.year_to = year;
}
}
</script>

화면에 랜더링 되는 YearPicker에 default 값을 할당하는 부분을 살펴보자.

this.year_from = String(fromYear); 

Date 객체로 부터 얻어 온 년도를 this.year_from 에 할당하면, year_from은 YearPicker 컴포넌트의 :year에 바인딩되게 된다.

<year-picker
:year="year_from"
@change="changeFromYear"
/>

사용자가 날짜를 변경하게 되면, 이미 선언한 bootstrap-datepicker의 event callback 함수가 실행이 되게 된다.

mounted: function() {
var that = this;
$(this.$el).datepicker({
'autoclose':true,
'minViewMode':2,
'maxViewMode':2,
'format':'yyyy'
}).on('changeDate', function(e){
//parent의 YearPicker에 선언된 change 이벤트 실행
that.$emit('change',String(e.date.getFullYear()));
})
;
}

날짜 변경시 발생되는 callback 함수에서 parent의 YearPicker에 선언된 change 이벤트를 실행 시키고, 최종적으로 changeFromYear 함수가 실행이 되게 된다.

<year-picker
:year="year_from"
@change="changeFromYear"
/>

child 컴포넌트인 YearPicker에서 변경된 날짜 값을 parent의 data에 반영시키므로 화면에서 데이터를 제어 할 수 있게 된다.

changeFromYear(year) {
this.year_from = year;
}

우리는 간단하게 YearPicker 컴포넌트를 구현해 보았고, 사용하는 예제를 살펴 보았다.

아래의 소스는 YearPicker와 동일한 방식으로 구현한 MonthPicker와 Datepicker이다. YearPicker와는 크게 차이가 없으니, MonthPicker를 이해했다면 쉽게 이해할 수 있을 것이다.

MonthPicker

<template>
<div class="input-group date" style="width:120px;">
<input type="text" class="form-control" v-model="yearmonth" />
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</template>
<script>
export default {
name: 'month-picker',
props: {
yearmonth: String
},
mounted: function() {
var that = this;
$(this.$el).datepicker({
'autoclose':true,
'minViewMode':1, //month까지 선택할수 있게 선언
'maxViewMode':2,
'format':'yyyy.mm' //날짜 포맷

}).on('changeDate', function(e){
var year = e.date.getFullYear();
var month = e.date.getMonth() + 1;
if(month < 10) month = '0' + month;
that.$emit('change',String(year)+'.'+String(month));
});
},
updated: function(){
$(this.$el).datepicker('update', this.yearmonth);
}
}
</script>

DatePicker

<template>
<div class="input-group date" style="width:150px;">
<input type="text" class="form-control" v-model="date" />
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</template>
<script>
export default {
name: 'date-picker',
props: {
date: String
},
mounted: function() {
var that = this;
$(this.$el).datepicker({
'autoclose':true,
'minViewMode':0, //day까지 선택할수 있게 선언
'maxViewMode':2,
'format':'yyyy.mm.dd' //날짜 포맷

}).on('changeDate', function(e){
var year = e.date.getFullYear();
var month = e.date.getMonth() + 1;
if(month < 10) month = '0' + month;
var day = e.date.getDate();
that.$emit('change',String(year)+'.'+String(month)+'.'+day);
});
},
updated: function(){
$(this.$el).datepicker('update', this.date);
}
}
</script>

--

--