/ Layout

Responsive draggable and resizable grid layout for VueJS

Responsive draggable and resizable grid layout for VueJS

VueResponsiveGridLayout

Responsive draggable and resizable grid layout for VueJS. Its responsiveness is based on breakpoints (similar to Bootstrap).

News

Now you can make both normal and responsive layout.

It works with Vuex nice as well.

And it's partly coded in Typescript.

Example

  • Clone project.
  • run $ npm run serve

Usage

NPM

npm install vue-responsive-grid-layout

Registration

import {VueResponsiveGridLayout, VueGridItem, VueGridLayout } from 'vue-responsive-grid-layout'

Vue.component('vue-responsive-grid-layout', VueResponsiveGridLayout)
Vue.component('vue-grid-item', VueGridItem)
Vue.component('vue-grid-layout', VueGridLayout)

Registration as plugin

import Vue from 'vue'
import VueResponsiveGridLayout from 'vue-responsive-grid-layout'

Vue.use(VueResponsiveGridLayout)

Simple example

<template>
    <VueResponsiveGridLayout
        @layout-update="onLayoutUpdate"
        @layout-change="onLayoutChange"
        @layout-init="onLayoutInit"
        @width-change="onWidthChange"
        @breakpoint-change="onBreakpointChange"
        :layouts="layouts"
        :compactType="'vertical'"
        :breakpoint="breakpoint"
        :cols="cols"
        ref="layout"
    >
    <template slot-scope="props">
      <VueGridItem v-for="item in props.layout"
              :i="item.i"
              :w.sync="item.w"
              :h.sync="item.h"
              :x="item.x"
              :y="item.y"
              :immobile.sync="item.immobile"
              :containerWidth="props.containerWidth"
              :rowHeight="props.rowHeight"
              :isDraggable="true"
              :isResizable="true"
              :className="'grid-item'"
              :cols="props.cols"
              :heightFromChildren="false"
              :maxRows="props.maxRows"
      >
          <div>Test</div>
      </VueGridItem>
    </template>
    </VueResponsiveGridLayout>
</template>

<script>

export default {
      public onLayoutUpdate(layout: Layout, layouts: ResponsiveLayout, last) {
          this.updateLayout({layout, breakpoint: this.breakpoint});
      }
    
      public onLayoutChange(layout: Layout, layouts: ResponsiveLayout, breakpoint: Breakpoint) {
          this.updateLayout({layout, breakpoint});
      }
    
      public onLayoutInit(layout, currentLayouts, cols, breakpoint) {
          this.updateCols({cols});
          this.updateBreakpoint({breakpoint});
          this.updateLayout({layout, breakpoint});
      }
    
      public onBreakpointChange(breakpoint: Breakpoint) {
          this.updateBreakpoint({breakpoint});
      }
    
      public onWidthChange(width: number, cols: number) {
          this.updateCols({cols});
      }
}
</script>

API

Works with Vuex.

Vue Responsive Grid Layout uses scoped slot inside to get some props.

<slot :containerWidth="width" :layout="layout" :rowHeight="rowHeight" :cols="cols" :maxRows="maxRows">

You can use it to send containerWidth, layout, rowHeight, cols and maxRows for grid-items.

.sync

Sync modifier is used on `w` and `h` props to make them reactive for external changes, 
when :heightFromChildren is set to `true`

Props VueResponsiveGridLayout

@Prop({
    type: Boolean,
    required: false,
})
public autoSize: boolean;

@Prop({
    type: Number,
    required: false,
    default: 12,
})
public cols: number;

@Prop({
    type: String,
    required: false,
    default: 'vertical',
})
public compactType: CompactType;

@Prop({
    type: Array,
    required: false,
    default: () => [5, 5],
})
public margin: [number, number];

@Prop({
    type: Array,
    required: false,
    default: () => [5, 5],
})
public containerPadding: [number, number] | null;

@Prop({
    type: Number,
    required: false,
    default: 10,
})
public rowHeight: number;

@Prop({
    type: Number,
    required: false,
    default: Infinity,
})
public maxRows: number;

@Prop({
    type: Boolean,
    required: false,
    default: true,
})
public isDraggable: boolean;

@Prop({
    type: Boolean,
    required: false,
    default: true,
})
public isResizable: boolean;

@Prop({
    type: Boolean,
    required: false,
    default: false,
})
public preventCollision: boolean;

@Prop({
    type: Boolean,
    required: false,
    default: true,
})
public useCSSTransforms: boolean;

// Responsive config
@Prop({
    type: String,
    required: false,
    default: 'vue-responsive-grid-layout',
})
public className: string;

@Prop({
    type: String,
    required: false,
    default: 'lg',
})
public breakpoint: Breakpoint;

@Prop({
    type: Object,
    required: false,
    default: () => ({ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }),
})
public breakpoints: { [key: string]: number };

@Prop({
    type: Object,
    required: false,
    default: () => ({ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }),
})
public colsAll: { [key: string]: number };

@Prop({
    type: Object,
    required: false,
    default: () => ({}),
})
public layouts: { [key: string]: Layout };

Description

autoSize

cols

Number of cols. Default is 12.

compactType

Type of compacting layout. Default "vertical".

margin

Margin of grid-items.

containerPadding

Width of container, it is needed to calculate the width of items.

rowHeight

Height of one grid unit row for placeholder.

maxRows

Max rows in layout.

isDraggable

Items can be dragged.

isResizable

Items can be resized.

preventCollision

Preventing collisions. Makes some grid items static.

useCSSTransforms

Uses transform css property for changing positions and size.

className

Defines additional classes for grid layout.
Default css class is vue-responsive-grid-layout.

breakpoint

Actual breakpoint. Default is "lg".

breakpoints

Breakpoints object which define width for breakpoints.

Default { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }.

colsAll

Defines cols for given breakpoints.

Default { lg: 12, md: 6, sm: 4, xs: 2, xxs: 1 }.

layouts

Layouts object for example:

{
    "lg" : [
        { x: 0, y: 0, w: 1, h: 1, i: "1" },
        { x: 1, y: 0, w: 1, h: 1, i: "2" },
    ],
    "md" : [
        { x: 0, y: 1, w: 1, h: 1, i: "1" },
        { x: 1, y: 1, w: 1, h: 1, i: "2" },
    ]
}

Events VueResponsiveGridLayout

@layout-update(layout: Layout, layouts: ResponsiveLayout, last: boolean)

@layout-change(layout: Layout, layouts: ResponsiveLayout, breakpoint: Breakpoint)

@layout-init(layout: Layout, layouts: ResponsiveLayout, cols: number, breakpoint: Breakpoint);

@width-change(width: number, cols: number)

@breakpoint-change(breakpoint: Breakpoint)

@add-child(child: Vue)

@remove-child(child: Vue)

Function on VueResponsiveGridLayout

resizeAllItems(width: number, compactType: CompactType, defaultSize = false, mode = false)

Props VueGridLayout

@Prop({
    type: String,
    required: false,
    default: 'vue-grid-layout',
})
public className: string;

@Prop({
    type: Object,
    required: false,
})
public styles: object;

@Prop({
    type: Boolean,
    required: false,
})
public autoSize: boolean;

@Prop({
    type: Number,
    required: false,
    default: 12,
})
public cols: number;

@Prop({
    type: String,
    required: false,
    default: '',
})
public draggableCancel: string;

@Prop({
    type: String,
    required: false,
    default: '',
})
public draggableHandle: string;

@Prop({
    type: String,
    required: false,
    default: 'vertical',
})
public compactType: CompactType;

@Prop({
    required: false,
    validator: (value) => {
        if (!value) {
            return true;
        }
        return validateLayout(value, 'layout');
    },
})
public layout: Layout;

@Prop({
    type: Array,
    required: false,
    default: () => [5, 5],
})
public margin: [number, number];

@Prop({
    type: Array,
    required: false,
    default: () => [5, 5],
})
public containerPadding: [number, number] | null;

@Prop({
    type: Number,
    required: false,
    default: 10,
})
public rowHeight: number;

@Prop({
    type: Number,
    required: false,
    default: Infinity,
})
public maxRows: number;

@Prop({
    type: Boolean,
    required: false,
    default: true,
})
public isDraggable: boolean;

@Prop({
    type: Boolean,
    required: false,
    default: true,
})
public isResizable: boolean;

@Prop({
    type: Boolean,
    required: false,
    default: false,
})
public preventCollision: boolean;

@Prop({
    type: Boolean,
    required: false,
    default: true,
})
public useCSSTransforms: boolean;

@Prop({
    type: Number,
    required: true,
})
public width: number;

Description

className

Defines additional classes for grid layout.
Default css class is vue-grid-layout.

autoSize

cols

Number of cols. Default is 12.

compactType

Type of compacting layout. Default "vertical".

layout

Layout array.

margin

Margin of grid-items.

containerPadding

Padding of layout.

rowHeight

Height of one grid unit row for placeholder.

maxRows

Max rows in layout.

isDraggable

Items can be dragged.

isResizable

Items can be resized.

preventCollision

Preventing collisions. Makes some grid items static.

useCSSTransforms

Uses transform css property for changing positions and size.

width

Width of grid layout. Is set from inside of VueGridLayout.

Events VueGridLayout

@layout-update(layout: Layout, last: boolean)

@add-child(child: Vue)

@remove-child(child: Vue)

Props VueGridItem

@Prop({
    type: Number,
    required: false,
    default: 12,
})
public cols: number;

@Prop({
    type: Number,
    required: true,
    default: 0,
})
public containerWidth: number;

@Prop({
    type: Number,
    required: false,
    default: 10,
})
public rowHeight: number;

@Prop({
    type: Array,
    required: false,
    default: () => [10, 10],
})
public margin: number[];

@Prop({
    type: Number,
    required: false,
    default: Infinity,
})
public maxRows: number;

@Prop({
    type: Array,
    required: false,
    default: () => [5, 5],
})
public containerPadding: number[];

// CORDS

@Prop({
    type: Number,
    required: true,
})
public x: number;

@Prop({
    type: Number,
    required: true,
})
public y: number;

@Prop({
    type: Number,
    required: true,
})
public w: number;

@Prop({
    type: Number,
    required: true,
})
public h: number;

@Prop({
    type: Number,
    required: false,
    default: 0,
})
public minW: number;

@Prop({
    type: Number,
    required: false,
    default: Infinity,
})
public maxW: number;

@Prop({
    type: Number,
    required: false,
    default: 0,
})
public minH: number;

@Prop({
    type: Number,
    required: false,
    default: Infinity,
})
public maxH: number;

// ID
@Prop({
    type: String,
    required: true,
})
public i: string;

// Functions
@Prop({
    type: Function,
})
public onDragStart: () => void;

@Prop({
    type: Function,
})
public onDrag: () => void;

@Prop({
    type: Function,
})
public onDragStop: () => void;

// Flags
@Prop({
    type: Boolean,
    default: false,
})
public isDraggable: boolean;

@Prop({
    type: Boolean,
    default: false,
})
public isResizable: boolean;

@Prop({
    type: Boolean,
    default: false,
})
public immobile: boolean;

@Prop({
    type: Boolean,
    default: true,
    required: false,
})
public canBeResizedWithAll: boolean;

// Use CSS transforms instead of top/left
@Prop({
    required: false,
    type: Boolean,
    default: true,
})
public useCSSTransforms: boolean;

@Prop({
    required: false,
    type: Boolean,
    default: false,
})
public usePercentages: boolean;

// Others
@Prop({
    required: false,
    type: String,
    default: 'vue-grid-item',
})
public className: string;

@Prop({
    required: false,
    type: String,
    default: 'vue-grid-draggable-container',
})
public dragContainerClass: string;

// Selector for draggable handle
@Prop({
    required: false,
    type: String,
    default: '',
})
public handle: string;

// Selector for draggable cancel
@Prop({
    required: false,
    type: String,
    default: '',
})
public cancel: string;

// Child
@Prop({
    type: Vue,
    required: false,
})
public component: Vue;

@Prop({
    type: Object,
    required: false,
})
public componentProps: object;

@Prop({
    type: Number,
    required: false,
    default: 2,
})
public defaultSize: number;

// Internal components

@Prop({
    type: Object,
    required: false,
})
public resizableProps: object;

@Prop({
    type: Object,
    required: false,
})
public draggableCoreProps: object;

@Prop({
    type: Boolean,
    default: true,
})
public noTouchAction: boolean;

@Prop({
    type: String,
    default: 'none',
})
public touchAction: string;

@Prop({
    required: false,
    type: Boolean,
    default: false,
})
public heightFromChildren: boolean;

@Prop({
    required: false,
    type: Boolean,
    default: false,
})
public placeholder: boolean;

Description

cols

Cols number default 12.

containerWidth

Width of container. Provided for counting of size and cords.

rowHeight

Row height. Default infinite.

margin

Margin of elements. Default [10, 10].

maxRows

Max rows in layout.

containerPadding

Padding of container. Default [5, 5].

x

X cord for item.

y

Y cord for item.

w

Width of item.

h

Height of item.

minW

Min width for item when resized.

maxW

Max width for item when resized.

minH

Min height for item when resized.

maxH

Max height for item when resized.

i

Id of item as string. Must be unique for items.

isDraggable

Enable draggable mode.

isResizable

Enable resizable mode.

immobile

Makes item static.

canBeResizedWithAll

Determinate if item can be resized with all by resizeAllItems() function.

useCSSTransforms

usePercentages

Uses percentages to count coords.

className

Class name for item. Default vue-grid-item.

dragContainerClass

Class for dragContainer in item.

handle

Selector for draggable handel.

cancel

Selector for draggable cancel.

component

Component to render inside grid item. You can use slot instead.

componentProps

Props for component inside grid item.

defaultSize

Default size of item. This size can be used to determinate size of items after resizeAllItems().

resizableProps

Props for resizable item.

draggableCoreProps

Props for draggable core item.

noTouchAction

Enable/disable touch action style after dragged.

touchAction

Touch action value after dragged.

heightFromChildren

Determinate if item should have height get from child element.

placeholder

Determinate if item is a placeholder.

GitHub