Vue 디렉티브를 활용하여 제가 현업에서 쓴 코드를 일부 소개하려합니다. Vue 디렉티브 개념은 이전 글을 참고해주세요.
구현할 체크박스
1. vue-js선언
// 표시할 데이터 리스트
this.dataList = [
{key:'first', val:'01'},
{key:'second', val:'02'},
{key:'third', val:'03'},
{key:'fourth', val:'04'},
{key:'fifth', val:'05'},
];
// 체크박스의 v-model 파라미터(vue에서 체크박스 구현시 v-model 파라미터는 꼭 배열로 선언해야합니다.)
this.checkList = [];
2. html
<table>
<thead>
<tr>
<th><input type="checkbox" v-mocheckbox:prdGroupCheckbox v-model="checkList" v-bind:value="0" v-if="dataList.length>0"></th>
<th>key</th>
<th>val</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,idx) in dataList">
<th><input type="checkbox" class="prdGroupCheckbox" v-mocheckbox:prdGroupCheckbox v-model="checkList" v-bind:value="item.val" v-if="dataList.length>0"></th>
<th>{{item.key}}</th>
<th>{{item.val}}</th>
</tr>
</tbody>
</table>
<!-- 전체 체크 버튼 -->
<input type="checkbox" id="checkall" v-mocheckbox:checkitem v-model="checkList" v-bind:value="0" v-if="dataList.length>0>
전체 체크 버튼의 value를 0으로 주었고 나머지는 리스트의 값들의 value는 0이 아닌 유니크 값으로 주어야합니다.
v-mocheckbox:checkitem의 v-mocheckbox는 디렉티브명이고 뒤에 checkitem은 파라미터이며 class명을 파라미터로 넘긴 것입니다.
<!-- 리스트 체크 버튼 -->
<input type="checkbox" class="checkitem" v-mocheckbox:checkitem v-model="checkList" v-bind:value="item.val" v-if="dataList.length>0">
전체 체크 버튼과 동일하게 v-mocheckbox는 디렉티브명과 파라미터 checkitem를 넘겨줍니다.
주의) 태그에 v-if="dataList.length>0"를 쓴 이유는 해당 화면이 display:none과 같이 화면이 show/hide 될 경우 v-model에 relendering이 필요하기 때문에 작성한 코드입니다. 또한 해당 화면을 호출할 경우 this.dataList를 초기화해야 relendering이 됩니다.
3. vue-directive checkbox 구현
Vue.directive("mocheckbox",{
bind: function(el, binding, vnode) {
var vdirective = vnode.data.directives,
vModel;
for(var i = 0, vDirLength = vdirective.length ; i < vDirLength ; i++) {
//console.log(vdirective[i].name );
if(vdirective[i].name == "model"){
//vModel = vdirective[i].expression;
vModel = vdirective[i];
break;
}
}
var selected = vModel.value;
var selectedCnt = 5;
var childClass="checkitem";
if(binding.arg) {
childClass=binding.arg;
}
$(el).off("click").on("click", function (e) {
if($(e.currentTarget).prop("checked") == true && $(e.currentTarget).val() == "0") { // 전체 체크박스 클릭
selected.splice(0,selected.length);
selected.push($(e.currentTarget).val());
$("."+childClass).each(function(index,item){
if(selected.indexOf($(item).val()) == -1) {
selected.push($(item).val());
}
});
selectedCnt = selected.length-1; // 자식 체크박스 수
} else if($(e.currentTarget).prop("checked") == false && $(e.currentTarget).val() == "0") { // 전체 체크박스 해제
selected.splice(selected.indexOf($(e.currentTarget).val()),1);
//해제됨
$("."+childClass).each(function(index,item){
if($(item).is(":checked")) {
$(item).prop("checked", false);
selected.splice(selected.indexOf($(item).val()),1);
}
});
} else if($(e.currentTarget).prop("checked") == true && $(e.currentTarget).val() != "0") { // 단일 리스트 체크박스 클릭
var temp = 0;
try {
temp = $("."+childClass).length;
} catch (e) {
temp = 0;
}
selectedCnt = temp; // 자식 체크박스 수
if(typeof temp != 'object') {
temp = 0;
}
if(selected.indexOf($(e.currentTarget).val()) == -1) { // 단일 리스트 체크박스 해제
selected.push($(e.currentTarget).val());
}
if(selected.length >= selectedCnt) {
selected.push("0");
}
} else if($(e.currentTarget).prop("checked") == false && $(e.currentTarget).val() != "0") {
var temp = selected.indexOf("0");
if(temp > -1) {
selected.splice(temp,1);
}
selected.splice(selected.indexOf($(e.currentTarget).val()),1);
}
});
},
inserted: function(el, binding, vnode){
},
update: function (el, binding, vnode) {
}
});
html에서 v-mocheckbox:checkitem 클래스명을 파라미터로 넘겼으며, binding.arg로 파라미터(클래스명)을 받습니다.
vnode.data.directives 프로퍼티를 통해서 바인딩된 v-model을 가져옵니다. 체크/해제 시 v-model의 값을 수정합니다. v-model은 배열로 선언했기 때문에 배열의 값을 push, splice 함수를 통해 수정합니다.
위의 코드는 4가지 경우의 수를 구현했습니다. - 전체 체크박스 클릭 => 모든 체크박스가 클릭됨
- 전체 체크박스 해제 => 모든 체크박스가 해제됨
- 단일 리스트 체크박스 클릭 => 단일 체크박스가 체크되며 모든 단일 박스가 클릭되면 전체 체크박스도 체크됩니다.
- 단일 리스트 체크박스 해제 => 단일 체크박스가 해제되면 전체 체크박스도 해제됩니다.
저는 v-model과 클래스명 두가지를 이용해서 v-directive를 구현했습니다. 혹시나 클래스명말고 다른 파라미터로 구현할 수 있다면 공유해주시면 좋을 것 같습니다. ^^오늘 글은 간단한 v-directive 체크박스 구현 코드를 공유해보았습니다. 다음에 좀 더 좋은 코드가 생각나면 공유할 수 있도록 하겠습니다!!!
'Vue' 카테고리의 다른 글
Vue - Vuex (0) | 2022.03.25 |
---|---|
Vue에서 fontawesome 설치 및 적용 (0) | 2022.02.16 |
Vue - 팝업 창에서 뒤로가기 구현 (0) | 2022.02.07 |
Vue 컴퍼넌트(Component) - 페이징 처리 (0) | 2021.06.10 |
Vue 디렉티브(directive) 개념 (0) | 2021.06.01 |
댓글