Skip to content
Snippets Groups Projects
sidebar: auto

Guide

Quickstart

Install the package vue-draggable-grid via your favourite package manager. Include the library in your project:

import draggableGrid from "vue-draggable-grid";

Vue.use(draggableGrid);

// Now create your app as usual

An example usage could look like this:

<template>
  <drag-grid v-model="items" :cols="4" :rows="4">
    <template #item="item">
      {{ item.data.text }}
    </template>
  </drag-grid>
</template>

<script>
export default {
  name: "YourComponent",
  data() {
    return {
      items: [
        {
          x: 1,
          y: 3,
          w: 2,
          h: 2,
          key: "item1",
          data: { text: "Hello world 1" },
        },
        {
          x: 2,
          y: 2,
          w: 2,
          h: 1,
          key: "item2",
          data: { text: "Hello world 2" },
        },
        {
          x: 3,
          y: 1,
          w: 1,
          h: 1,
          key: "item3",
          data: { text: "Hello world 3" },
        },
      ],
    };
  },
};
</script>

Blocking fields

A field (or cell) can be blocked via the disabledFields prop. The prop receives an array of objects, containing the coordinates of the blocked fields.

disabledFields: [
  { x: 1, y: 1 },
  { x: 2, y: 3 },
];

Prevent items from being dragged

To disable dragging of a specific item, simply set the attribute disabled of the item to true.

someDisabledItems: [
    { key: "key1", x: 1, y: 3, w: 1, h: 1, data: {} },
    { key: "key2", x: 2, y: 2, w: 1, h: 1, data: {} },
    { key: "key3", x: 3, y: 1, w: 1, h: 1, data: {}, disabled: true },
    { key: "key4", x: 1, y: 2, w: 1, h: 1, data: {}, disabled: true },
]

The highlighted items are not draggable.

Disabling the grid

If the boolean property disabled is set for the whole grid, the grid itself is disabled, and items can't be moved.

::: tip NOTICE A disabled grid only prevents changing the data inside the grid. If the data changes from outside of the grid, the grid will rerender. :::

Programmatic validation of movements

It is also possible to supply a function to dynamically or programmatically hinder fields from being moved to, and items from being moved. This can be done by supplying a function which takes the x and y coordinates of the field as well as the key of the item. If false is returned, the movement is prohibited. The highlight which appears when dragging an element is also disabled for this field.

Examples for such methods are the following:

function blockField(x, y, key) {
  // We won't move items with ID 'obj8' and nothing into (3, 3) and (4, 3)
  if (x === 3 && y === 3) return false;
  if (x === 4 && y === 3) return false;
  return key !== "obj8";
}

function blockAllMoving() {
  return false;
}

Changing the highlight

The highlight is the grey-bordered rectangle which appears when dragging over a field.

Custom highlight

To customize the highlight, use the highlight slot inside the grid component.

<drag-grid v-model="items" :cols="3" :rows="2">
  <template #highlight>
    <div ref="highlight" class="custom-highlight">
      This is a custom highlight with a custom style!
    </div>
  </template>
</drag-grid>

Disabled highlight

To disable the highlight, use the no-highlight prop.

Displaying the loading of items

If the grid is supplied with the loading prop, it will be in a loading status. In this status it is disabled, like if disabled where true, but the grid is filled with elements inside the loader slot. This provides the ability to do something like more realistic skeleton loaders.

Changing items on move

It is possible to make changes to an item once it moved successfully. One can supply a function in the validate-element prop which gets called on a moved item and can make (in place) changes to it. Such a function could look like this:

function randomKey(element) {
  if (element.key.length !== 1) return;
  element.key += Math.random().toString(36).replace("0.", "");
}

This method changes the key of a moved item to a random string if the key has a length of 1. This is used inside example 2 (the tic-tac-toe game).

Functional item properties

Properties of items don't have to be Numbers, Strings and Objects, they can also be functions returning those types. They will automatically be called with a grid object containing the gridId as well as the context.

A singular item could look like this:

[
  {
    x: (grid) => {
      return grid.gridId === "lesson-plan" ? this.lesson1X : 0;
    },
    y: (grid) => {
      return grid.gridId === "lesson-plan" ? this.lesson1Y : 0;
    },
    w: 1,
    h: this.lesson1Length,
    key: "lesson1",
    data: {
      text: this.lessonData.lesson1,
    },
  },
];

Items can also have custom extra properties. They will however be reset after moving. An example where these are used is Example 5.

Listening to grid changes

There are two ways to process changes made by dragging and dropping items: the input event and the itemChanged event.

The input event works together with the value prop so one can use v-model to supply the grid and have changes made automatically. The event returns the grid how it would look if the item moved to the specific location.

::: warning Notice that this event is only possible if your item properties are basic types, functional items are not supported and the properties will be reset to undefined. :::

The itemChanged event returns the moved item with following attributes:

let eventData = {
  context: String, // Context of the origin grid (same as the target's)
  data: Object, // Data Object of the item
  gridId: String, // ID of the target grid
  h: Number, // Height of the item
  key: String, // Key of the item
  mouseX: Number, // Mouse position on the element relative to
  mouseY: Number, //    the center of the top left rectangle
  originGridId: String, // ID of the origin grid
  w: Number, // Width of the item
  x: Number, // New x position (col) of the item
  y: Number, // New y position (row) of the item
};

This event doesn't change the grid, this change has to be made separately. This is useful if e.g. a direct API request is needed.

Multiple grids

To connect multiple grids they need to have the same context. If you supply the same string to the context prop of two grids, the items can be moved interchangeably.

::: warning Items are not deleted from the source grid if moved to a different one. You have to build a mechanism for this yourself. Examples for such a mechanism can be found in Examples 4 and 5. :::

To handle movements from one grid to another, the attributes gridId and originGridId of the event will help.