Skip to content

Instantly share code, notes, and snippets.

@SEUH
Last active November 6, 2018 13:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SEUH/e4088195aa0afae44ae598093840acfb to your computer and use it in GitHub Desktop.
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.
<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