Skip to content
Advertisement

How to create a tree-view in vue-js with clickable components opening up a vue-js modal?

I want to create a tree-view component in Vue-JS to display my JSON data. But I have an additional requirement where I need to launch a VueJS modal on clicking any of the data fields of JSON view. I looked up at several npm modules that does display data in tree-view but I am not sure how to modify them to make them clickable and launch vue-js modal. This is the code I am currently using to display tree-view but none of the fields are clickable.

assets.vue

    <template>

  <div>  

        <h1>The Assets Page</h1>
        <!--<p>{{response}}</p>-->
        <tree-view v-on:click="openGroupModal()" :data="response._embedded.assets" :options="{maxDepth: 0, rootObjectKey: 'Assets'}"></tree-view>
      </div>

</template>
<script>
import axios from 'axios'
import GroupModal from '../assets/assetdetails.vue'
import Vue from 'vue'
import VModal from 'vue-js-modal'
Vue.use(VModal, { dynamic: true })

export default {
  name: 'service',
  data () {
   return {
   response: [],
   errors: []
   }
   },
   
 created () {
      this.callRestService()
    },
 methods: {
   callRestService () {
    axios.get('http://localhost:8080/rest/assets')
   .then(response => {
   // JSON responses are automatically parsed.
   this.response = response.data
   })
   .catch(e => {
    this.errors.push(e)
  })
},
openGroupModal(){

  this.$modal.show(GroupModal,
  {
      draggable: true,
      resizable: true,
      scrollable: true,
      height: "auto",
      width:"50%"
    })
}
 }
}
</script>
<style>
</style> 

main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import VueRouter from 'vue-router'
import VModal from 'vue-js-modal'
import App from './App.vue'
import TreeView from 'vue-json-tree-view'

import { routes } from './routes';


Vue.use(VueRouter);
Vue.use(VModal, { dynamic: true })
Vue.use(TreeView)
//Vue.config.productionTip = false

const router = new VueRouter({

  routes  
});


/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

Any ideas?

UPDATE: I tried Jacob’s answer but that didn’t help me launch the modal. I tried this:

<template>

  <div>  

        <h1>The Assets Page</h1>
        <!--<p>{{response}}</p>-->
        <div @click.capture="openGroupModal($event)">
        <tree-view :data="response._embedded.assets" :options="{maxDepth: 0, rootObjectKey: 'Assets'}"></tree-view>
        </div>
      </div>

</template>
<script>
import axios from 'axios'
import GroupModal from '../assets/assetdetails.vue'
import Vue from 'vue'
import VModal from 'vue-js-modal'
Vue.use(VModal, { dynamic: true })

export default {
  name: 'service',
  data () {
   return {
   response: [],
   errors: []
   }
   },
   
 created () {
      this.callRestService()
    },
 methods: {
   callRestService () {
    axios.get('http://localhost:8080/rest/assets')
   .then(response => {
   // JSON responses are automatically parsed.
   this.response = response.data
   })
   .catch(e => {
    this.errors.push(e)
  })
},
openGroupModal($event){
  console.log("The console message",$event.target);
  this.$modal.show(GroupModal,
  {
      draggable: true,
      resizable: true,
      scrollable: true,
      height: "auto",
      width:"50%"
    })
}
 }
}
</script>
<style>
</style> 

Advertisement

Answer

well.. a div container can work for you

use @click.capture. (once .capture is added, an event targeting an inner element is handled here before being handled by that element, from Vue doc)

and you can get exactly which element has been clicked on by using $event.target

e.g.

<template>
  <div @click.capture="openGroupModal($event)">
    <tree-view :data="{1:1,2:{a:'a'}}" :options="{maxDepth: 3}"></tree-view>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  methods:{
    openGroupModal($event){
      console.log($event.target);
      // other codes for showing modal and etc...
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

Tested on HelloWorld.vue component in https://codesandbox.io/s/nkwk2k095l

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement