Front-End

[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 

 

[개발자 가이드 문서]

 

Leave a Reply

error: Content is protected !!