문제
Kendo라는 UI 프로그램과 Vue를 이용해 화면 기능을 구현하는 프로젝트였다.
아래와 같이 Conent를 선택해서, Add 버튼을 누르면 아래 Grid로 이동해야 된다.
selected된 항목들을 바로 계산할 수 있도록 아래와 같이 computed를 사용했다.
allContentGridData는 상위 Grid에 노출되는 Data이다.
computed: {
selectedDataItems () {
return this.allContentGridData.filter(item => item.selected === true)
}
}
checkbox를 클릭할 때마다 selectedDateItems가 실행될 거라 생각하고, checkBox 선택 시 onSelectionChange 메소드가 실행되도록 하였다. selected = true 값은 false로 false는 true로 변경하는 메소드다.
methods: {
onSelectionChange (event) {
event.dataItem[this.selectedField] = !event.dataItem[this.selectedField]
}
}
Add 버튼을 클릭하면 computed에 있는 selectedDataItems를 이용해 선택된 항목들만 아래 Grid로 보내준다.
method: {
clickAddButton: function () {
const selectedContents = this.selectedDataItems
this.excludeContent({
gridName: 'allContent',
contents: selectedContents
})
this.includeContent({
gridName: 'documentContent',
contents: selectedContents
})
}
}
그런데, checkbox를 선택했음에도 clickAddButton이 실행될 때, this.selectedDataItems 결과가 빈 배열로 나왔다.
원인
console을 찍어보니 체크 박스 선택 시 onSelectionChange가 실행되고 나서, computed의 selectedDateItems가 실행되지 않고 있었다. 원인을 찾아보니, Vue에서는 Object나 Array의 내부항목이 변경될 경우 감지가 되지 않는다.
selectedDateItems는 배열의 값을 직접 변경해주고 있었고, 이는 Vue의 반응성 시스템에서는 감지되지 않았던 것이다.
event.dataItem[this.selectedField] = !event.dataItem[this.selectedField]
Vue.set(object, key, value) 메소드를 사용하면 변경이 감지되지 않는 객체나 Array 내부 항목이더라도 반응성 속성을 추가 할 수 있다.
해결
Vue.set 메소드를 사용하여, 아래와 같이 변경해주었고, Vue가 변경을 감지하면서 selectedDateItems도 잘 실행되어 선택된 항목들을 가져올 수 있었다.
methods: {
onSelectionChange (event) {
let checked = event.event.target.checked
Vue.set(event.target.dataItems[i], this.selectedField, checked)
}
}
참고 자료
https://ftfuture.tistory.com/46