[Vuejs] 체크박스 한개만 체크 되도록 구현

2021. 5. 22. 17:56프론트엔드/Vue.js

728x90

 

 

Vue.js로 체크박스를 한번도 구현해본적 없었는데,

체크박스를 라디오버튼처럼 한 개만 체크된 상태로 구현해달라는 요건이 생김.

회사에서 시도 해봤는데, 

전혀 감이 잡히지 않아 집에서 시도.

 

핵심은 제이쿼리는 Dom요소로 제어하지만, Vue로 구현한다면 값으로 컨트롤 해야 한다는 것이었음.

 

 

 


 

[ 방법 1 ] : CheckBox.vue에 바로 적용

 

CheckBox.vue 

<template>
    <div>
      <input type="checkbox" v-model='isAllChecked' value="" @click="allCheck" >전체체크
      <input type="checkbox" v-model='checkedValues' value="1" @change="clickFunc" :true-value="yes" :false-value="no" >1
      <input type="checkbox" v-model='checkedValues' value="2"  @change="clickFunc">2
      <input type="checkbox" v-model='checkedValues' value="3"  @change="clickFunc">3
     {{checkedValues}}
     {{this.isAllChecked}}
     {{removeValue}}
    </div>
</template>

<script>
export default {
    props:['removeValue'],
    data(){
        return{
            checkedValues:[],
            isAllChecked:true
        }
    },
    methods: {
        clickFunc(event) {
          for(let i=0; i<this.checkedValues.length;i++){
            if(this.checkedValues[i] !== event.target.value){
            console.log(this.checkedValues[i])
            this.checkedValues.splice(i,1);
            }
          }
        },
        allCheck(){
            if(!this.isAllChecked){
                for(let i=1; i<4; i++){
                    this.checkedValues.push(i)
                }
               this.isAllChecked = true;
            }else{
                 this.checkedValues=[]

                this.isAllChecked  = false;
            }
             this.$emit('checkClick',this.checkedValues)
        }
    },
    computed:{
         
    }
}
</script>

<style>

</style>

 

체크박스가 체크되면, checkedValues라는 배열에 체크된 value값이 담김.

 

 근데, 이게 @click 발생시 메서드에서 checkedValues 값을 찍어보면 바로 들어가는게 아니라 클릭이벤트가 끝나구 들어감 (예를들어  '1'을 체크한 시점에 @click에서 checkedValues값을 찍어보면, 아무 값도 없고 {{checkedValues}}에는 '1'이 찍힘. 다음으로 '2'를 체크한 시점에 @click에서  checkedValues값을 찍어보면, '1'만 찍히고,  {{checkedValues}}에는 '1,2'가 찍힘) .

 

그래서 이벤트 시점에 checkedValues에는 현재 체크한 value값을 받을 수 없어서 'event.target.value'로 현재 체크한 값을 받아오도록 함.

 

체크박스 click 이벤트 시점이 아니구 change 이벤트 시점에 체크한  value값을 제외한 값들을 제거하는 로직으로 구현

@click으로 하니까 checkedValues에 값이 없을 때는 바로 체크가 되지만, 값이 있을 때는 해당 값의 이전 체크를 지우기 까진 해주지만 현재 체크한 체크박스가 바로 체크가 안되서 두 번 클릭을 해줘야 하는 문제 발생 

@change로 하면, 잘됨.

 


 

[ 방법 2 ] : 부모 TodoInput.vue에사 CheckBox컴포넌트를 적용하여 구현

 

CheckBox.vue 

<template>
    <div>
      <input type="checkbox" v-model='isAllChecked' value="" @click="allCheck" >전체체크
      <input type="checkbox" v-model='checkedValues' value="1" @change="clickFunc" :true-value="yes" :false-value="no" >1
      <input type="checkbox" v-model='checkedValues' value="2"  @change="clickFunc">2
      <input type="checkbox" v-model='checkedValues' value="3"  @change="clickFunc">3
     {{checkedValues}}
     {{this.isAllChecked}}
     {{removeValue}}
    </div>
</template>

<script>
export default {
    props:['removeValue'],
    data(){
        return{
            checkedValues:[],
            isAllChecked:true
        }
    },
    methods: {
        clickFunc(event) {
            let checkedVal = {
                targetChecked : event.target.value,
                checkedArr : this.checkedValues
            }
           this.$emit('checkClick',checkedVal)
        },
        allCheck(){
            if(!this.isAllChecked){
                for(let i=1; i<4; i++){
                    this.checkedValues.push(i)
                }
               this.isAllChecked = true;
            }else{
                 this.checkedValues=[]

                this.isAllChecked  = false;
            }
             this.$emit('checkClick',this.checkedValues)
        }
    },
    computed:{
         
    }
}
</script>

<style>

</style>

 

TodoInput.vue

<template>
  <div id="input">
      <input type="text" placeholder="이곳에 해야할 일을 적어주세요">
      <button id="inputBtn">입력</button>
      <CheckBox @checkClick="onlyOneChecked" ></CheckBox>
     childCheckValue{{childCheckValue}}
  </div>
</template>

<script>
import CheckBox from "./CheckBox.vue";

export default {
    data(){
        return{
            childCheckValue:[]
        }
    },
    components:{
        CheckBox
    },
    methods:{
        onlyOneChecked(checkedVal){
            this.childCheckValue = checkedVal.checkedArr
            for(let i=0; i<this.childCheckValue.length; i++){
                if(this.childCheckValue[i] !== checkedVal.targetChecked){
                    this.childCheckValue.splice(i,1)
                }
            }
        }
    }   
}
</script>

<style>

</style>
728x90