JS tr로 클릭 이벤트 처리하기

강정우·2023년 11월 27일
0

JavaScript

목록 보기
49/53
post-thumbnail

목표


아니 gif 왜 깨지는건데~ 개억울하잖슴~

  • 대충 아래 사진과 같다 사실 저 체크박스를(모양은 토글이지만 넘어가자) 정확히 aim하여 클릭하기란 정말 어려운 일이다.

  • 그래서 대충 id나 이름이나 여타 다른 컬럼을 클릭해도 체크박스가 활성화되도록 만들고싶었다.

방법

  • 방법은 매우 간단하다. 저기 input의 이벤트를 그냥 없애버리고
// vue.js 문법
@click="(event :Event) => {event.stopPropagation()}"

// 아님 더 간편하게
@click.stop
  • 그 위의 <tr>에 이벤트를 부여하는 것이다.

  • 만약 해당 컴포넌트에서만 사용한다면 그냥 state를 선언하면 되고 혹여나 다른 컴포넌트에서도 해당 체크 유무를 알아야한다면 그냥 통쨀 짤라다가 store로 state를 유지하면 된다.

  • 이벤트 버블링 캡쳐링

코드

  • 이제 코드를 알아보자.
<tbody>
  <tr v-for="item in displayVOList" 
  	:key="item.displayCode" 
    :id="`checkbox-${item.displayCode}`" 
	class="row" 
	@click="clickTr2Toggle(item.displayCode)"
  >
    <td class="center">
      <span class="chkList">
        <input type="checkbox" 
        	:id="item.displayCode" 
            :ref="`checkbox-${item.displayCode}`" 
			name="soundedit" 
			:checked="selectedDisplayList.includes(item.displayCode)" 
			@click="(event :Event) => {event.stopPropagation()}" 
		/>
        <label :for="item.displayCode"></label>
	  </span>
	</td>
    <td class="tdbar center">{{ item.displayCode }}</td>
    <td class="tdbar">{{ item.displayName }}</td>
    <td class="tdbar">{{ ... 
                   ...
  </tr>
</tbody>
  • 대강 코드를 설명하면 일단 tr을 반복을 돌리는데 displayVOList 만큼 돌린다.
clickTr2Toggle(displayCode: number) {
  const checkboxRef = this.$refs[`checkbox-${displayCode}`] as HTMLInputElement[];
  this.mkDisplayAry(!this.selectedDisplayList.includes(displayCode), displayCode);
  if (checkboxRef && checkboxRef.length > 0) {
    const checkbox = checkboxRef[0];
    checkbox.checked = !checkbox.checked;
    this.mkDisplayAry(checkbox.checked, displayCode);
  }
},
  • 그리고 tr 태그에 실제로 클릭이 대신 동작할 함수를 작성한다.
    위 코드에서 사실 ref는 작동하지 않는다 왜냐하면 ref를 사용하여 DOM 요소를 참조할 때,
    해당 요소가 Vue.js에 의해 렌더링된 후에야 참조가 가능하다.
    따라서 clickTr2Toggle 메서드가 호출되는 시점에는 아직 체크박스가 렌더링되지 않았다.

  • 그러나 체크박스는 v-for 디렉티브에 의해 이미 렌더링되어 있어야 하고 따라서 checkboxRef가 비어 있으면 안 되는데 뭐가 문제인지는 아직 파악하지 못 했다.

  • 그래서 mkDisplayAry 를 추가하여 해결하였다.
    사실 안되는 위 코드를 삭제하고 바로 mkDisplayAry에 물려도 되지만 원인을 찾으면 추후 보강하고자 냅뒀다.

mkDisplayAry(checked: boolean, value: number) {
  if (checked) {
    this.selectedDisplayList.push(value);
  } else {
    this.selectedDisplayList = this.selectedDisplayList.filter((el: number) => el !== value);
  }
},
  • 그리고 값을 받아서 만약 selectedDisplayList 배열에 들어있으면 빼고(filter메서드) 없으면 추가하여 해당 값을 이제 위 html 코드에서 input 태그의 값으로써 사용하였다.

혹은 input 값을 Array<Someting> 으로 잡아서 해당 배열을 갖고 조절해도 된다.

profile
智(지)! 德(덕)! 體(체)!

0개의 댓글