vue-grid-layout icon indicating copy to clipboard operation
vue-grid-layout copied to clipboard

Adding "ref" attribute to grid item

Open JanniePienaar77 opened this issue 3 years ago • 1 comments

Good day,
With Vue to quickly reference a dom element in a vue template, one can add ref attribute to the html. Can we add this to the grid-item as a property then it can be directly available, ie, we can programattically refere to a specific grid item in our script code, and add, components, etc to a specific item dynamically.

JanniePienaar77 avatar Jun 09 '22 06:06 JanniePienaar77

hi, I faced the same problem. After I try several days, I use it in this way and it works.

I use Vue 3+Typescript+vite. I tried to grab a new grid-item form outside and dymanic add it into my gridLayout.

image

basically use this code: https://github.com/jbaysolutions/vue-grid-layout/blob/master/website/docs/.vuepress/components/Example10DragFromOutside.vue

I faced the problem that $children is removed in Vue3,so I changed the usage of Vue 2 into Vue 3.

// sample code
this.$refs.gridlayout.$children[this.layout.length].$refs.item.style.display = "none";

// change into
var gridlayout = ref()
gridlayout.value.$refs.item.children[index].style.display = "none";

but by this way, I can't call the method "calXY()" in gridItem. the problematic code in the sample:

// get the grid-item
let el = this.$refs.gridlayout.$children[index];

// call grid-item function to calculate the new position
let new_pos = el.calcXY(mouseXY.y - parentRect.top, mouseXY.x - parentRect.left);

At first I used gridLayout ref,trying to get its children(gridItem) like the sample. it's like this: gridlayout.value.$refs.item.children[index].__vueParentComponent.proxy.calcXY() It works only under development mode.

and I tried to use ref. Because grid-item is rendered by v-for, so its ref need to write a function to get every item. I only need the last grid-item ref.

<grid-item  
v-for="item in layout"  
:key="item.i" 
:ref="setItemRef"  
:x="item.x"  
:y="item.y"  
:w="item.w"  
:h="item.h"  
:i='item.i'  
>  
your item here
</grid-item>
// get the last grid-item ref
var temp_item = ref()

function setItemRef(el:any){
  // if you need the all ref, you can't use the ref<Array<type>> and push el into array directly
  // as long as you haven't released the left mouse button, it will keep changing the ref value
  // so if you push it into the array directly, array will get longer and longer
  temp_item.value = el
}

so now I have the last grid-item ref. the first time you drag it into the gridlayout, temp_item.value will get null. so just need an if:

if(temp_item.value){
  let el = temp_item.value
  el.dragging = {"top": mouseXY.y - parentRect.top, "left": mouseXY.x - parentRect.left}
  let new_pos = el.calcXY(mouseXY.y - parentRect.top, mouseXY.x - parentRect.left)
}

because only the new item will call drag() and dragend(), so it only affects the latest one (meaning the newly added gridItem).

this works well in production mode. I just learned Vue 3 several months. if anything wrong, plz tell me. hope this comes in handy

UTing1119 avatar Nov 18 '22 03:11 UTing1119