Solution:
Use the mounted hook of Vue component to fetch the dynamic HTML subtree then add 'Click' event handler for eligible node elements of the subtree to trigger element selection.
Additionally use mouseover & mouseout event Handler to toggle interactive styling
Step 1: Setup the project with a vue component using v-html
<div id="app">
Create designs using Uinel
<div id="interactivecanvas" v-html="dynamicHTML"></div>
<div id="selectedElement">Selection: {{selectedElement.tagName}}</div>
</div>
Step 2: Add CSS styles to indicate a Selectable Element
.selectable{
box-shadow: 0 0 0 2px green;
}
Step 3: Add a mounted hook to fetch dynamic HTML Sub-tree
mounted(){
// List of selectable Elements. Uses css selector syntax
let selectableElements = ['li', 'span', 'button']
selectableElements[0] = '#interactivecanvas '+selectableElements[0]
let canvasContents = document.querySelectorAll(selectableElements.join(',
#interactivecanvas '))
.....
Step 4: Iterate through Sub-tree Elements and add Event Handlers for Selection
mounted(){
...
for(let i=0; i<canvasContents.length; i++){
...
canvasContents[i].addEventListener('click',e=>{
e.stopPropagation();
this.selectElement(e)
})
...
}
Step 5: Optional! you can add mouseover & mouseout event Handler to toggle interactive styling.
Check the example below. View in full page.
new Vue({
el: '#app',
data() {
return {
selectedElement: {},
dynamicHTML: `
<div class="header">
<nav class="nav">
<ul id="nav">
<li>Home</li>
<li>Contact Us</li>
<li>About Us</li>
</ul>
<div id="card">
<div id="usercard">
<span>Sona</span>
<span>▼</span>
</div>
<button>New Project</button>
</div>
<nav>
</div>
`
}
},
mounted(){
// List of selectable Elements. Uses css selector syntax
let selectableElements = ['li', 'span', 'button']
selectableElements[0] = '#interactivecanvas '+selectableElements[0]
let canvasContents = document.querySelectorAll(selectableElements.join(', #interactivecanvas '))
for(let i=0; i<canvasContents.length; i++){
// Add mouseover & mouseout event Handler to toggle styles
canvasContents[i].addEventListener('mouseover',(e)=>{
e.stopPropagation();
e.currentTarget.classList.add("selectable")
})
canvasContents[i].addEventListener('mouseout',(e)=>{
e.stopPropagation();
e.currentTarget.classList.remove("selectable")
})
// Event to fire Selection action. Use 'hover' or 'click'
canvasContents[i].addEventListener('click',e=>{
e.stopPropagation();
this.selectElement(e)
})
}
},
methods:{
selectElement(e){
console.log('Selected '+e.currentTarget)
this.selectedElement = e.currentTarget
}
}
})
* {
box-sizing: border-box;
}
body {
font-family: 'Verdana'
}
ul {
list-style: none;
}
.header {
background: rgba(245,246,247);
padding: 20px;
}
.nav {
display: flex;
}
.nav > ul > li {
display: inline;
margin: 20px;
}
.nav button {
border: 2px solid gray;
border-radius: 9999px;
padding: 12px 20px;
}
.nav #card {
display: flex;
align-items: center;
}
#usercard {
margin: 20px;
padding: 10px;
}
.selectable{
box-shadow: 0 0 0 2px green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
Create designs using Uinel
<div id="selectedElement">Selection: {{selectedElement.tagName}}</div>
<div id="interactivecanvas" v-html="dynamicHTML"></div>
</div>