0

I want to make Treeview like this:

A 
|--B
|  |--BC1
|  |   |--BC1-S
|  |      |--BC1-1
|  |      |--BC1-2
|  |__BC2
|      |--BC2-S
|         |--BC2-1
|         |--BC2-2
|--G
   |--GC1
       |--GC1-S1
       |  |--GC1-1
       |  |--GC1-2
       |
       |--GC1-S2
          |--GC1-3
          |--GC1-4

I have data came from API like this: (ID, Root, Attribute, Depth)

datas: [ 
  [1,  0,  'A',     0],
  [2,  1,  'B',     1], 
  [3,  2,  'BC1',   2],
  [4,  3,  'BC1-S', 3],
  [5,  4,  'BC1-1', 4],
  [6,  4,  'BC1-2', 4],
  [7,  2,  'BC2',   2],
  [8,  7,  'BC2-S', 3],
  [9,  8,  'BC2-1', 4],
  [10, 8,  'BC2-2', 4],
  [11, 1,  'G',     1],
  [12, 11, 'GC1',   2],
  [13, 12, 'GC1-S1',3],
  [14, 13, 'GC1-1', 4],
  [15, 13, 'GC1-2', 4],
  [16, 11, 'GC1-S2',3],
  [17, 16, 'GC1-3', 4],
  [18, 16, 'GC1-4', 4]
]

Template:

<tr v-for="data in datas" :key="data[0]">
<td>
  <div v-if="data[3] == 0" class="tt tt-parent" style="left: 0px;">
    <div class="content">{{ data[2] }}</div>
  </div>

  <div v-else-if="data[3] == 1" class="tt tt-parent" style="left: 47px;">
    <div class="tail" style="height: 26px; width: 47px; left: -23.5px;"></div>
    <div class="content">{{ data[2] }}</div>
  </div>

  <div v-else-if="data[3] == 2" class="tt tt-parent" style="left: 95px;">
    <div class="tail" style="height: 26px; width: 47px; left: -23.5px;"></div>
    <div class="content">{{ data[2] }}</div>
  </div>

  <div v-else-if="data[3] == 3" class="tt tt-parent" style="left: 143px;">
    <div class="tail" style="height: 26px; width: 47px; left: -23.5px;"></div>
    <div class="content">{{ data[2] }}</div>
  </div>

  <div v-else-if="data[6] == 4" class="tt" style="left: 191px;">
    <div class="tail" style="height: 26px; width: 47px; left: -23.5px;"></div>
    <div class="content">{{ data[2] }}</div>
  </div>
</td> 
</tr>

CSS:

.tt-table div.tt {
    display:inline-block;
    position:relative;
}

.tt-table div.tt div.content {
    border:1px gray solid;
    border-radius: 2px;
    z-index: 10;
    padding:0 4px 0 5px;
    position:relative;
    background-color: #dbffbe;
    width: 100px;
}

.tt-table div.tt div.tail {
    border:2px gray solid;
    border-right: 0;
    border-top: 0;
    position:absolute;
    border-radius: 2px;
    bottom: 11px;
    left: -10px;
    z-index: 0;
}

Hi all, I want to create a treeview like this.

  1. the problem is i can not connect the line between A-G, B-BC2, GC1-GC1-S2.
  2. How to create a dynamic script, especially when the data is later more than 50

This is one of the failed examples:

1 Answer 1

2

first you need to structure your data into parent-child relation (use internal java script function to modify the array data into parent-child object or modify it at server)

then you can use recursive rendering like below.

// modified data from array
var data = {
  id: 1,
  name: 'A',
  open: true,  // default open
  children: [{
      name: 'B',
      children: [{
        name: 'BC1',
        children: [{
          name: 'BC1-S',
          children: [{
              name: 'BC1-1'
            },
            {
              name: 'BC1-2'
            }
          ]
        }]
      },{
        name: 'BC2',
        children: [{
          name: 'BC2-S',
          children: [{
              name: 'BC2-1'
            },
            {
              name: 'BC2-2'
            }
          ]
        }]
      }]
    },
    {
      name: 'G',
      children: [{
        name: 'GC1',
        children: [{
          name: 'GC1-S1',
          children: [{
              name: 'GC1-1'
            },
            {
              name: 'GC1-2'
            }
          ]
        },{
          name: 'GC1-S2',
          children: [{
              name: 'GC1-3'
            },
            {
              name: 'GC1-4'
            }
          ]
        }]
      }]
    }
  ]
}

// define the item component
Vue.component('item', {
  template: '#item-template',
  props: {
    model: Object
  },
  data: function() {
    return {
      open: this.model.open
    }
  },
  computed: {
    isFolder: function() {
      return this.model.children &&
        this.model.children.length
    }
  },
  methods: {
    toggle: function() {
      if (this.isFolder) {
        this.open = !this.open
      }
    }
  }
})

new Vue({
  el: '#main',
  data: {
    treeData: data
  }
})
body {
  font-family: Menlo, Consolas, monospace;
  color: #444;
}

.tree-view {}

.tree-view>ul {
  padding-left: 16px;
}

.tree-view li {
  list-style-type: none;
  margin: 0;
  padding: 10px 5px 0;
  position: relative;
}

.tree-view li:last-child {
  margin-bottom: 10px;
}

.tree-view li::after,
.tree-view li::before {
  content: '';
  left: -30px;
  position: absolute;
  right: auto;
}

.tree-view li::before {
  border-left: 1px solid #405567;
  height: calc(100% + 10px);
  top: 0;
  width: 1px;
}

.tree-view li::after {
  border-top: 1px solid #405567;
  height: 20px;
  top: 20px;
  width: 35px;
}

.tree-view .item {
  border: 1px solid #405567;
  border-radius: 2px;
  background-color: #fff;
  display: inline-block;
  padding: 2px 6px;
  text-decoration: none;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
}

.tree-view .folder {
  background-color: #fbf897;
}

.tree-view>ul>li::after,
.tree-view>ul>li::before {
  border: 0;
}

.tree-view li:last-child::before {
  height: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>

<script type="text/x-template" id="item-template">
  <li>
    <div class="item" :class="{folder: isFolder}" @click="toggle">
      <span v-if="isFolder">{{ open ? '-' : '+' }}</span> {{ model.name }}
    </div>
    <ul v-show="open" v-if="isFolder">
      <item v-for="(model, index) in model.children" :key="index" :model="model">
      </item>
    </ul>
  </li>
</script>

<div class="tree-view" id="main">
  <ul>
    <item :model="treeData">
    </item>
  </ul>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @Jag. You are a hero

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.