Front-End

[Vue.js + Vuetify.js] v-treeview 자식노드를 동적으로 disabled 처리하는 방법????

부모노드를 선택했을 때 자식 노드를 선택하지 못하도록 Disable 처리하고, 반대로 부모노드 선택을 해제했을 때 자식노드를 다시 선택할 수 있도록 기능 구현을 하고 있다. 

사실 이런 기능은 사용자 싫수에 따른 오류를 없애기위해 필요한 기능이지, 개발자 입자에서는 필요없다고 보는 기능이다. 

disable 처리가 아닌방법으로 부모노드를 선택했을 경우에 후 순위 작업으로 자식노드를 선택했을 때 선택할 수 없다는 메세지를 뛰운 후 선택해제해주는 방법도 생각해볼 수 있다.

 

 

[Vuetify.js] treeview 사용법 정리

vuetify.js 라이브러리의 treeview를 사용하는 방법에 대한 정리입니다. v-treeview API는 아래 링크를 참고하면 되고, Props, Functions, Events 등의 정보를 확인할 수 있습니다. v-treeview API API for the v-..

playground.naragara.com

트리를 구성하는 기본 데이터는 다음과 같다. (this.tree.originData)

[
   {
      "id":22,
      "parentId":0,
      "name":"개발부서",
      "treeDepth":0,
      "orderSeq":1,
      "children":[
         {
            "id":39,
            "parentId":22,
            "name":"부서1",
            "treeDepth":1,
            "orderSeq":1,
            "children":[
               {
                  "id":69,
                  "parentId":39,
                  "name":"1234",
                  "treeDepth":2,
                  "orderSeq":1,
                  "children":[
                     
                  ]
               },
               {
                  "id":83,
                  "parentId":39,
                  "name":"부서-1-1",
                  "treeDepth":2,
                  "orderSeq":1,
                  "children":[
                     
                  ]
               }
            ]
         },
         {
            "id":40,
            "parentId":22,
            "name":"부서2",
            "treeDepth":1,
            "orderSeq":2,
            "children":[
               {
                  "id":41,
                  "parentId":40,
                  "name":"부서2-1",
                  "treeDepth":2,
                  "orderSeq":1,
                  "children":[
                     
                  ]
               }
            ]
         }
      ]
   },
   {
      "id":39,
      "parentId":22,
      "name":"부서1",
      "treeDepth":1,
      "orderSeq":1,
      "children":[
         {
            "id":69,
            "parentId":39,
            "name":"1234",
            "treeDepth":2,
            "orderSeq":1,
            "children":[
               
            ]
         },
         {
            "id":83,
            "parentId":39,
            "name":"부서-1-1",
            "treeDepth":2,
            "orderSeq":1,
            "children":[
               
            ]
         }
      ]
   },
   {
      "id":40,
      "parentId":22,
      "name":"부서2",
      "treeDepth":1,
      "orderSeq":2,
      "children":[
         {
            "id":41,
            "parentId":40,
            "name":"부서2-1",
            "treeDepth":2,
            "orderSeq":1,
            "children":[
               
            ]
         }
      ]
   },
   {
      "id":41,
      "parentId":40,
      "name":"부서2-1",
      "treeDepth":2,
      "orderSeq":1,
      "children":[
         
      ]
   },
   {
      "id":69,
      "parentId":39,
      "name":"1234",
      "treeDepth":2,
      "orderSeq":1,
      "children":[
         
      ]
   },
   {
      "id":83,
      "parentId":39,
      "name":"부서-1-1",
      "treeDepth":2,
      "orderSeq":1,
      "children":[
         
      ]
   }
]

JSON데이터 정렬해주는 사이트를 이용하여 String타입의 json데이터를 정렬하였다.

트리 노드를 disable처리하기 위해서는 <v-treeview> 태그 속성 값 중에 다음 속성을 추가해준다

item-disabled="locked"

그런다음,

트리를 구성하는 데이터에 locked 값에 대한 true, false를 지정해주어야한다. 이부분을 동적으로 구현해야한다.

검색을 해보았지만 자료가 많지않아 직접구현해야했다.

 
    <v-treeview
      v-model="tree.treeData"
      ref="treeview"
      item-key="id"
      :items="tree.itemsTree"
      :active.sync="tree.active"
      :selectable="isSelectTree"
      :activatable="isActivatable"
      :selection-type="selectionType"
      :return-object="returnObject"
      :disabled="isDisabled"
      @update:active="selectNode"
      @input="selectCheckBox"
      rounded
      hoverable
      item-disabled="locked">
    >
      <template slot="label" slot-scope="{ item, open, active }">
        <div @click="active ?  $event.stopPropagation() : null">
          <v-icon v-if="!item.icon">{{ open ? 'mdi-folder-open' : 'mdi-folder' }}</v-icon>
          <v-icon v-else>{{ 'mdi-'+ item.icon }}</v-icon>
          {{ item.name }}
        </div>
      </template>
    </v-treeview>
 
트리를 구성할 기본데이터를 가지고 트리 구조로 노드를 생성할 때 부모Id값을 갖는 자식(chidren)노드를  찾아 locked를 값을 true로 설정해준다.
그런 처리를 해주는 메서드는 아래와 같다.
  data: () => ({
    tree: {
      treeData: [],
      itemsTree: [],
      choicedNode: {},
      openNode: [],
      active: [],
      originData: [],
    },
  }),
  
  ........생략..............
  
    selectCheckBox(e) {
      console.log('checkbox clicked', e);

      // 부모 노드값을 갖은 자식노드를 찾아 locked= true 처리 한다.
      console.log(`## tmpArr = ${JSON.stringify(this.tree.originData)}`);
      let tmpArr = [];
      this.tree.treeData.forEach((id) => {
          tmpArr = this.makeLockTreeArray(this.tree.originData, id);
      });

      if (tmpArr.length > 0) {
        this.tree.itemsTree = tmpArr;
      }

      this.$emit('treeCheckClicked', this.submit());
    },
    makeLockTreeArray(array, treeId) {
      const topLevel = 0;
      const treeNodes = [];

      array.forEach((item) => {
        if (item.treeDepth === topLevel) {
          const node = item;
          node.locked = false;
          node.children = this.makeLockNode(array, topLevel + 1, item.id, treeId);
          treeNodes.push(node);
        }
      });
      return treeNodes;
    },
    makeLockNode(array, level, parentId, treeId) {
      const childNodes = [];
      array.forEach((item) => {
        if (item.treeDepth === level && item.parentId === parentId) {
          const node = item;
          if (item.parentId === treeId) {
            node.locked = true;
          } else {
            node.locked = false;
          }
          node.children = this.makeLockNode(array, level + 1, item.id, treeId);
          childNodes.push(node);
        }
      });
      return childNodes;
    },

그런데 초기화가 안된다. 체크 해제를 하면 원래의 값으로 돌아가는데, 트리에 반영이 안된다. 

또 한가지 문제는 여러개의 부모노드를 선택하는경우 가장 마지막 노드에만 locked:true가 반영이된다는 문제가 있다.


또 하나의 문제가 있다. 트리 뎁스가 깊어지면 , 부모 노드값이 다르기 때문에 자식노드가 disabled 처리가 되지않는다.

서로 물고 있는 부모노드id값이 다르기 때문이다.

 

아 어떻게 하지…..

머리가 안돌아간다.

 

다른 방법 으로 상위 그룹을 선택 시 하위 노드가 아닌 그룹 노드 ID를 리턴하고 그룹에 하위 노드가 하나라도 선택이 안된 경우는 하위 노드 ID 리턴하도록하는 메소드

getCustomSelectNode() {
  // treeview 컴포넌트의 모든 nodes 정보, object로 되어 있어서 속성 값만 array로 변경
  const nodes = Object.values(this.$refs.treeview.nodes);

  // 선택이 된 그룹 노드 추출
  const selectParentNodes = nodes.filter((row) => {
	const node = row;
	return node.children.length && node.isSelected;
  });

  return nodes.reduce((acc, row) => {
	const node = row;
	let mat = [];

	// 현재 노드의 부모 노드가 선택됐는지 확인
	if (selectParentNodes.length) {
	  mat = selectParentNodes.filter((prnt) => {
		const parentNode = prnt;
		return parentNode.item.id === node.item.parentId;
	  });
	}

	// 노드가 선택되어 있고 부모 노드가 없거나 선택이 안된 경우 push
	if (node.isSelected && !mat.length) {
	  acc.push(this.returnObject ? node.item : node.item.id);
	}

	return acc;
  }, []);
},

 

[REFERENCE]

 

Leave a Reply

error: Content is protected !!