Skip to content

Commit 304c894

Browse files
authored
Fix some bugs in the vue3 branch and keep it consistent with the API of the master branch (jbaysolutions#557)
1 parent bada5b9 commit 304c894

File tree

2 files changed

+233
-63
lines changed

2 files changed

+233
-63
lines changed

src/App.vue

Lines changed: 228 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,233 @@
11
<template>
2-
<GridLayout
3-
:value.sync="layout"
4-
:col-num="12"
5-
:row-height="30"
6-
:is-draggable="true"
7-
:is-resizable="true"
8-
:is-mirrored="false"
9-
:vertical-compact="true"
10-
:margin="[10, 10]"
11-
:use-css-transforms="true"
12-
@layout-updated="layout = $event"
13-
@layout-ready="layout = $event"
14-
>
15-
16-
<GridItem v-for="item in layout"
17-
:x="item.x"
18-
:y="item.y"
19-
:w="item.w"
20-
:h="item.h"
21-
:i="item.i"
22-
:key="item.i">
23-
{{item.i}}
24-
</GridItem>
25-
</GridLayout>
2+
<div id="app">
3+
<h1 style="text-align: center">Vue Grid Layout</h1>
4+
<!--<pre>{{ layout | json }}</pre>-->
5+
<div>
6+
<div class="layoutJSON">
7+
Displayed as <code>[x, y, w, h]</code>:
8+
<div class="columns">
9+
<div class="layoutItem" v-for="item in layout" :key="item.i">
10+
<b>{{item.i}}</b>: [{{item.x}}, {{item.y}}, {{item.w}}, {{item.h}}]
11+
</div>
12+
</div>
13+
</div>
14+
</div>
15+
<div id="content">
16+
<button @click="decreaseWidth">Decrease Width</button>
17+
<button @click="increaseWidth">Increase Width</button>
18+
<button @click="addItem">Add an item</button>
19+
<button @click="addItemDynamically">Add an item dynamically</button>
20+
<!-- Add to show rtl support -->
21+
<button @click="changeDirection">Change Direction</button>
22+
<input type="checkbox" v-model="draggable"/> Draggable
23+
<input type="checkbox" v-model="resizable"/> Resizable
24+
<input type="checkbox" v-model="mirrored"/> Mirrored
25+
<input type="checkbox" v-model="responsive"/> Responsive
26+
<input type="checkbox" v-model="preventCollision"/> Prevent Collision
27+
<div style="margin-top: 10px;margin-bottom: 10px;">
28+
Row Height: <input type="number" v-model="rowHeight"/> Col nums: <input type="number" v-model="colNum"/>
29+
Margin x: <input type="number" v-model="marginX"/> Margin y: <input type="number" v-model="marginY"/>
30+
</div>
31+
<grid-layout
32+
:margin="[parseInt(marginX), parseInt(marginY)]"
33+
v-model:layout="layout"
34+
:col-num="parseInt(colNum)"
35+
:row-height="rowHeight"
36+
:is-draggable="draggable"
37+
:is-resizable="resizable"
38+
:is-mirrored="mirrored"
39+
:prevent-collision="preventCollision"
40+
:vertical-compact="compact"
41+
:use-css-transforms="true"
42+
:responsive="responsive"
43+
@layout-created="layoutCreatedEvent"
44+
@layout-before-mount="layoutBeforeMountEvent"
45+
@layout-mounted="layoutMountedEvent"
46+
@layout-ready="layoutReadyEvent"
47+
@layout-updated="layoutUpdatedEvent"
48+
@breakpoint-changed="breakpointChangedEvent"
49+
>
50+
<grid-item v-for="item in layout" :key="item.i"
51+
:static="item.static"
52+
:x="item.x"
53+
:y="item.y"
54+
:w="item.w"
55+
:h="item.h"
56+
:i="item.i"
57+
:min-w="item.minW"
58+
:max-w="item.maxW"
59+
:min-x="item.minX"
60+
:max-x="item.maxX"
61+
:min-y="item.minY"
62+
:max-y="item.maxY"
63+
:preserve-aspect-ratio="item.preserveAspectRatio"
64+
@resize="resize"
65+
@move="move"
66+
@resized="resized"
67+
@container-resized="containerResized"
68+
@moved="moved"
69+
>
70+
<test-element :text="item.i" @removeItem="removeItem($event)"></test-element>
71+
</grid-item>
72+
</grid-layout>
73+
<hr/>
74+
</div>
75+
</div>
2676
</template>
2777

28-
<script lang="ts">
29-
import {defineComponent} from 'vue'
30-
import VueGridLayout from "./components";
31-
32-
export default defineComponent({
33-
name: 'App',
34-
components: {
35-
GridLayout: VueGridLayout.GridLayout,
36-
GridItem: VueGridLayout.GridItem,
37-
},
38-
data() {
39-
return {
40-
layout: [
41-
{"x": 0, "y": 0, "w": 2, "h": 2, "i": "0"},
42-
{"x": 2, "y": 0, "w": 2, "h": 4, "i": "1"},
43-
{"x": 4, "y": 0, "w": 2, "h": 5, "i": "2"},
44-
{"x": 6, "y": 0, "w": 2, "h": 3, "i": "3"},
45-
{"x": 8, "y": 0, "w": 2, "h": 3, "i": "4"},
46-
{"x": 10, "y": 0, "w": 2, "h": 3, "i": "5"},
47-
{"x": 0, "y": 5, "w": 2, "h": 5, "i": "6"},
48-
{"x": 2, "y": 5, "w": 2, "h": 5, "i": "7"},
49-
{"x": 4, "y": 5, "w": 2, "h": 5, "i": "8"},
50-
{"x": 6, "y": 3, "w": 2, "h": 4, "i": "9"},
51-
{"x": 8, "y": 4, "w": 2, "h": 4, "i": "10"},
52-
{"x": 10, "y": 4, "w": 2, "h": 4, "i": "11"},
53-
{"x": 0, "y": 10, "w": 2, "h": 5, "i": "12"},
54-
{"x": 2, "y": 10, "w": 2, "h": 5, "i": "13"},
55-
{"x": 4, "y": 8, "w": 2, "h": 4, "i": "14"},
56-
{"x": 6, "y": 8, "w": 2, "h": 4, "i": "15"},
57-
{"x": 8, "y": 10, "w": 2, "h": 5, "i": "16"},
58-
{"x": 10, "y": 4, "w": 2, "h": 2, "i": "17"},
59-
{"x": 0, "y": 9, "w": 2, "h": 3, "i": "18"},
60-
{"x": 2, "y": 6, "w": 2, "h": 2, "i": "19"}
61-
]
78+
<script>
79+
import GridItem from './components/GridItem.vue';
80+
import GridLayout from './components/GridLayout.vue';
81+
import TestElement from './components/TestElement.vue';
82+
import CustomDragElement from './components/CustomDragElement.vue';
83+
import {getDocumentDir, setDocumentDir} from "./helpers/DOM";
84+
let testLayout = [
85+
{"x":0,"y":0,"w":2,"h":2,"i":"0", resizable: true, draggable: true, static: false, minY: 0, maxY: 2},
86+
{"x":2,"y":0,"w":2,"h":4,"i":"1", resizable: null, draggable: null, static: true},
87+
{"x":4,"y":0,"w":2,"h":5,"i":"2", resizable: false, draggable: false, static: false, minX: 4, maxX: 4, minW: 2, maxW: 2, preserveAspectRatio: true},
88+
{"x":6,"y":0,"w":2,"h":3,"i":"3", resizable: false, draggable: false, static: false},
89+
{"x":8,"y":0,"w":2,"h":3,"i":"4", resizable: false, draggable: false, static: false},
90+
{"x":10,"y":0,"w":2,"h":3,"i":"5", resizable: false, draggable: false, static: false},
91+
{"x":0,"y":5,"w":2,"h":5,"i":"6", resizable: false, draggable: false, static: false},
92+
{"x":2,"y":5,"w":2,"h":5,"i":"7", resizable: false, draggable: false, static: false},
93+
{"x":4,"y":5,"w":2,"h":5,"i":"8", resizable: false, draggable: false, static: false},
94+
{"x":6,"y":3,"w":2,"h":4,"i":"9", resizable: false, draggable: false, static: true},
95+
{"x":8,"y":4,"w":2,"h":4,"i":"10", resizable: false, draggable: false, static: false},
96+
{"x":10,"y":4,"w":2,"h":4,"i":"11", resizable: false, draggable: false, static: false, minY: 4},
97+
{"x":0,"y":10,"w":2,"h":5,"i":"12", resizable: false, draggable: false, static: false},
98+
{"x":2,"y":10,"w":2,"h":5,"i":"13", resizable: false, draggable: false, static: false},
99+
{"x":4,"y":8,"w":2,"h":4,"i":"14", resizable: false, draggable: false, static: false},
100+
{"x":6,"y":8,"w":2,"h":4,"i":"15", resizable: false, draggable: false, static: false},
101+
{"x":8,"y":10,"w":2,"h":5,"i":"16", resizable: false, draggable: false, static: false},
102+
{"x":10,"y":4,"w":2,"h":2,"i":"17", resizable: false, draggable: false, static: false},
103+
{"x":0,"y":9,"w":2,"h":3,"i":"18", resizable: false, draggable: false, static: false},
104+
{"x":2,"y":6,"w":2,"h":2,"i":"19", resizable: false, draggable: false, static: false}
105+
];
106+
export default {
107+
name: 'app',
108+
components: {
109+
GridLayout,
110+
GridItem,
111+
TestElement,
112+
CustomDragElement,
113+
},
114+
data () {
115+
return {
116+
layout: JSON.parse(JSON.stringify(testLayout)),
117+
draggable: true,
118+
resizable: true,
119+
mirrored: false,
120+
responsive: true,
121+
preventCollision: false,
122+
compact: true,
123+
rowHeight: 30,
124+
colNum: 12,
125+
index: 0,
126+
marginX: 10,
127+
marginY: 10,
128+
}
129+
},
130+
mounted: function () {
131+
this.index = this.layout.length;
132+
},
133+
methods: {
134+
clicked: function() {
135+
window.alert("CLICK!");
136+
},
137+
increaseWidth: function() {
138+
let width = document.getElementById("content").offsetWidth;
139+
width += 20;
140+
document.getElementById("content").style.width = width+"px";
141+
},
142+
decreaseWidth: function() {
143+
let width = document.getElementById("content").offsetWidth;
144+
width -= 20;
145+
document.getElementById("content").style.width = width+"px";
146+
},
147+
removeItem: function(i) {
148+
console.log("### REMOVE " + i);
149+
const index = this.layout.map(item => item.i).indexOf(i);
150+
this.layout.splice(index, 1);
151+
},
152+
addItem: function() {
153+
// let self = this;
154+
//console.log("### LENGTH: " + this.layout.length);
155+
let item = {"x":0,"y":0,"w":2,"h":2,"i":this.index+"", whatever: "bbb"};
156+
this.index++;
157+
this.layout.push(item);
158+
},
159+
addItemDynamically: function() {
160+
const x = (this.layout.length * 2) % (this.colNum || 12);
161+
const y = this.layout.length + (this.colNum || 12);
162+
console.log("X=" + x + " Y=" + y)
163+
let item = {
164+
x: x,
165+
y: y,
166+
w: 2,
167+
h: 2,
168+
i: this.index+"",
169+
}
170+
this.index++;
171+
this.layout.push(item);
172+
},
173+
move: function(i, newX, newY){
174+
console.log("MOVE i=" + i + ", X=" + newX + ", Y=" + newY);
175+
},
176+
resize: function(i, newH, newW, newHPx, newWPx){
177+
console.log("RESIZE i=" + i + ", H=" + newH + ", W=" + newW + ", H(px)=" + newHPx + ", W(px)=" + newWPx);
178+
},
179+
moved: function(i, newX, newY){
180+
console.log("### MOVED i=" + i + ", X=" + newX + ", Y=" + newY);
181+
},
182+
resized: function(i, newH, newW, newHPx, newWPx){
183+
console.log("### RESIZED i=" + i + ", H=" + newH + ", W=" + newW + ", H(px)=" + newHPx + ", W(px)=" + newWPx);
184+
},
185+
containerResized: function(i, newH, newW, newHPx, newWPx){
186+
console.log("### CONTAINER RESIZED i=" + i + ", H=" + newH + ", W=" + newW + ", H(px)=" + newHPx + ", W(px)=" + newWPx);
187+
},
188+
/**
189+
* Add change direction button
190+
*/
191+
changeDirection() {
192+
let documentDirection = getDocumentDir();
193+
let toggle = "";
194+
if (documentDirection === "rtl") {
195+
toggle = "ltr"
196+
} else {
197+
toggle = "rtl"
62198
}
199+
setDocumentDir(toggle);
200+
//eventBus.$emit('directionchange');
201+
},
202+
layoutCreatedEvent: function(newLayout){
203+
console.log("Created layout: ", newLayout)
204+
},
205+
layoutBeforeMountEvent: function(newLayout){
206+
console.log("beforeMount layout: ", newLayout)
207+
},
208+
layoutMountedEvent: function(newLayout){
209+
console.log("Mounted layout: ", newLayout)
210+
},
211+
layoutReadyEvent: function(newLayout){
212+
console.log("Ready layout: ", newLayout)
213+
},
214+
layoutUpdatedEvent: function(newLayout){
215+
console.log("Updated layout: ", newLayout)
216+
},
217+
breakpointChangedEvent: function(newBreakpoint, newLayout){
218+
console.log("breakpoint changed breakpoint=", newBreakpoint, ", layout: ", newLayout );
63219
}
64-
}
65-
)</script>
220+
},
221+
}
222+
</script>
223+
224+
<style>
225+
#app {
226+
font-family: 'Avenir', Helvetica, Arial, sans-serif;
227+
-webkit-font-smoothing: antialiased;
228+
-moz-osx-font-smoothing: grayscale;
229+
/*text-align: center;*/
230+
color: #2c3e50;
231+
/*margin-top: 60px;*/
232+
}
233+
</style>

src/components/GridLayout.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
type: Boolean,
9393
default: true
9494
},
95-
value: {
95+
layout: {
9696
type: Array,
9797
required: true,
9898
},
@@ -136,7 +136,6 @@
136136
layouts: {}, // array to store all layouts from different breakpoints
137137
lastBreakpoint: null, // store last active breakpoint
138138
originalLayout: null, // store original Layout
139-
layout: JSON.parse(JSON.stringify(this.value))
140139
};
141140
},
142141
created () {
@@ -232,6 +231,9 @@
232231
this.updateHeight();
233232
});
234233
},
234+
'layout.length': function() {
235+
this.layoutUpdate();
236+
},
235237
layout: function () {
236238
this.layoutUpdate();
237239
},
@@ -335,7 +337,7 @@
335337
}
336338
337339
// Move the element to the dragged ___location.
338-
this.layout = moveElement(this.layout, l, x, y, true, this.preventCollision);
340+
moveElement(this.layout, l, x, y, true, this.preventCollision);
339341
compact(this.layout, this.verticalCompact);
340342
// needed because vue can't detect changes on array element properties
341343
this.eventBus.emit("compact");

0 commit comments

Comments
 (0)