Last active
November 6, 2018 13:25
-
-
Save SEUH/e4088195aa0afae44ae598093840acfb to your computer and use it in GitHub Desktop.
Create draggable elements between shadowdom and "normal" dom. Generally you can use this example with as many "dom's" as you want. This example uses Vue.js and Vue.Draggable.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<style> | |
.container { | |
position: absolute; | |
top: 0; | |
width: 50%; | |
height: 100%; | |
} | |
.left { | |
float: left; | |
left: 0; | |
background: #d4d4d4; | |
} | |
.right { | |
float: left; | |
right: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container left"> | |
<h1>Shadow Dom</h1> | |
<div id="shadow"> | |
</div> | |
</div> | |
<div class="container right"> | |
<h1>Normal Dom</h1> | |
<div id="normal"> | |
<draggable v-model="list2" class="dragArea" :options="{group:'people'}"> | |
<div v-for="(element, index) in list2" :key="index">{{element.name}}</div> | |
</draggable> | |
</div> | |
</div> | |
<script src="//cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> | |
<script src="//cdn.jsdelivr.net/npm/sortablejs@1.7.0/Sortable.min.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.15.0/vuedraggable.min.js"></script> | |
<script> | |
/** | |
* Vue.Draggable https://github.com/SortableJS/Vue.Draggable | |
* From Vue.Draggable example: https://jsfiddle.net/t3m5krea/2042/ | |
* | |
* Information: | |
* This was a test if you can use Vue.Draggable with a vue instance inside | |
* the shadow dom and you can. There is at the moment no JS only library | |
* which supports shadow dom's that's the reason why i've tried this. | |
* | |
* Important: | |
* Be aware that Vue.Draggable clones/mirrors the dragged object directly | |
* into the hovered container and therefore you need to add the element | |
* in the normal dom AND also in the shadow dom unless you want different | |
* styles for both "Dom's". Also, mutating a prop is an anti pattern in | |
* vue.js and you should use something like 'sync' or events but i wasn't | |
* sure how i would use that. | |
*/ | |
window.onload = function () { | |
// Create a shadow dom + container | |
let shadowContainer = document.getElementById('shadow'); | |
let shadowTree = shadowContainer.attachShadow({mode: 'open'}); | |
// Create a shadow root element | |
let containerDiv = document.createElement('div'); | |
containerDiv.name = 'containerDiv'; | |
shadowTree.appendChild(containerDiv); | |
// Vue component to render inside the shadow dom | |
Vue.component('InnerShadowDomContainer', { | |
props: ['list'], | |
template: '<draggable v-model.sync="list" class="dragArea" :options="{group:{ name:\'people\', pull:\'clone\'}}">' + | |
' <div v-for="(element, index) in list" :key="index">{{element.name}}</div>' + | |
' </draggable>', | |
mounted() { | |
console.log('Inner: ', this.list); | |
} | |
}); | |
// Create the 'main' vue instance | |
const vm = new Vue({ | |
el: "#normal", | |
data: { | |
list: [{ | |
name: "John" | |
}, { | |
name: "Joao" | |
}, { | |
name: "Jean" | |
}], | |
list2: [{ | |
name: "Juan" | |
}, { | |
name: "Edgard" | |
}, { | |
name: "Johnson" | |
}] | |
}, | |
methods: {}, | |
mounted() { | |
let _this = this; | |
/* | |
We need to pass the list to the child component therefore we create the | |
InnerShadowDomContainer from inside the vue instance of the normal dom. | |
Normally i would've made both containers inside a single vue component | |
and just pass the lists and the group to both of them but this is just | |
a showcase | |
*/ | |
new Vue({ | |
el: containerDiv, | |
render(h) { | |
console.log(_this.list); | |
return h('InnerShadowDomContainer', { | |
props: { | |
list: _this.list, | |
} | |
}); | |
}, | |
}); | |
}, | |
}); | |
}; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment