[Vue.js + Vuetify.js] 1개 이상의 트리(v-treeview)에서 부모 노드와 자식노드의 중복 체크 하는 방법
다음과 같은 선택가능한 treeview가 여러개 있다고 가정하자. Selection type은 leaf이다.
아래와 같이 1번의 트리의 경우 부모노드인 Applications 를 선택하였고, 2번의 경우 Applications의 자식노드인 Chrome:app 노드를 선택하였다.
1번에서 상위 부모노드를 선택하였음으로 2번 트리에서는 그 어떤 자식 노드도 선택할 수 없다면 1번과 2번의 트리의 중복 선택을 체크 하는 방법은????
<SelectTreeView v-for="(item, i) in treeData.treeItemList" :key=i
:id="i"
:treeItems="data.treeItems"
@remove="removeTree"
ref="refTreeComponent"
/>
data.treeItems 에는 트리를 구성하는 오브젝트값으로 구성된 배열이다.
아래는 여러개의 트리를 추가했을 때 제거하는 스크립트이다.
removeTree(id) {
const index = this.treeData.treeItemList.findIndex(f => f.id === id);
this.treeData.treeItemList.splice(index, 1);
},
[해결방법]
위 문제를 해결하는 스크립트는 다음과 같다.
fnCheckData(type) {
const msgArr = [];
let isAll = false;
const allDeptArr = [];
this.treeData.treeItemList.forEach((item, idx) => {
let obj = {};
// 트리별 선택된 노드
const deptStr = this.$refs.refTreeComponent[idx].getTreeSelected();
if (deptStr.length < 1) {
if (this.treeData.treeItemList.length > 1) {
obj.msg = `${idx + 1} 번째 트리 노드를 선택해라`;
} else {
obj.msg = '트리를 선택해라';
}
msgArr.push(obj);
}
this.data.treeDeptItems.forEach((dept, i) => {
if (i === 0 && deptStr.indexOf(dept.id) >= 0 && dept.treeDepth === 0) {
isAll = true;
}
if (idx > 0 && isAll) {
obj = {};
obj.msg = `${idx + 1} 번째 적용 선택이 전체일 경우 선택불가.)`;
msgArr.push(obj);
}
});
if (this.treeData.treeItemList.length === 1 && isAll && type === 'add') {
obj = {};
obj.msg = '선택이 전체인경우 추가 불가.';
msgArr.push(obj);
}
const tmpArr = deptStr.split('|');
tmpArr.forEach((x) => {
const objDept = {};
objDept.seq = idx;
objDept.deptId = x;
allDeptArr.push(objDept);
});
});
// 최종 체크
const obj = {};
console.log(`##allDeptArr-> ${JSON.stringify(allDeptArr)}`);
const treeIdArr = [];
allDeptArr.forEach((item, index) => {
if (index > 0) {
treeIdArr.push(this.searchtreeIdArr(item.deptId, allDeptArr, index));
}
});
let deptNames = '';
if (treeIdArr.length > 0) {
treeIdArr.forEach((pId) => {
const deptName = this.nodeName(pId);
if (deptName !== '') deptNames = deptNames.concat(', ', deptName);
});
if (deptNames.length > 0) {
obj.msg = `[${deptNames.slice(1, deptNames.length)}] 중복되는 노드 발견`;
msgArr.push(obj);
}
}
트리 노드 중복체크 하는 스크립트
searchtreeIdArr(deptId, allDeptArr, index) {
const deupNodeIds = [];
allDeptArr.forEach((dept, idx) => {
if (Number(deptId) === Number(dept.deptId) && idx < index) {
deupNodeIds.push(Number(dept.deptId));
} else {
this.data.treeDeptItems.forEach((item) => {
if (Number(deptId) === item.id) {
allDeptArr.forEach((innerDept, idx2) => {
if (item.treeIdArr === Number(innerDept.deptId) && idx2 < index) {
deupNodeIds.push(Number(innerDept.deptId));
}
});
}
});
}
});
return this.fnGetUniqueArr(deupNodeIds);
},
//배열 중복 제거 fn
fnGetUniqueArr(dupArr) {
const uniqueArr = dupArr.filter((element, index) => dupArr.indexOf(element) === index);
return uniqueArr;
},
트리뷰(v-treeview) 선택 불가(disabled) 처리 하는 방법은?
아래와 같이 이미 선택된 노드는 선택할 수 없도록 하는 방법도 있는 것 같다.
v-treeview의 속성값으로 item-disabled에 대한 값으로 “locked”를 설정 하고
이미 선택한 노드의 경우 트리 노드 구성하는 속성값으로 locked: true 옵션을 주면 된다.
가이드 문서의 내용은 가이드일뿐 실전에 적용하면 생각처럼 쉽게 처리 되지 않는다.
[Template]
<template>
<v-treeview
selectable
item-disabled="locked"
:items="items"
></v-treeview>
</template>
[Script]
<script>
export default {
data: () => ({
items: [
{
id: 1,
name: 'Applications :',
locked: true,
children: [
{ id: 2, name: 'Calendar : app' },
{ id: 3, name: 'Chrome : app' },
{ id: 4, name: 'Webstorm : app' },
],
},
{
id: 5,
name: 'Documents :',
children: [
{
id: 6,
name: 'vuetify :',
children: [
{
id: 7,
name: 'src :',
locked: true,
children: [
{ id: 8, name: 'index : ts' },
{ id: 9, name: 'bootstrap : ts' },
],
},
],
},
{
id: 10,
name: 'material2 :',
children: [
{
id: 11,
name: 'src :',
children: [
{ id: 12, name: 'v-btn : ts' },
{ id: 13, name: 'v-card : ts' },
{ id: 14, name: 'v-window : ts' },
],
},
],
},
],
},
{
id: 15,
name: 'Downloads :',
children: [
{ id: 16, name: 'October : pdf', locked: true },
{ id: 17, name: 'November : pdf', locked: true },
{ id: 18, name: 'Tutorial : html', locked: true },
],
},
{
id: 19,
name: 'Videos :',
children: [
{
id: 20,
name: 'Tutorials :',
children: [
{ id: 21, name: 'Basic layouts : mp4' },
{ id: 22, name: 'Advanced techniques : mp4' },
{ id: 23, name: 'All about app : dir' },
],
},
{ id: 24, name: 'Intro : mov' },
{ id: 25, name: 'Conference introduction : avi' },
],
},
],
}),
}
</script>
코드펜 : https://codepen.io/pen?editors=1010
[개발자 가이드 문서]