Newer
Older
import Example1Generic from "./Example1Generic.vue";
import Example2TicTacToe from "./Example2TicTacToe.vue";
import Example3Counters from "./Example3Counters.vue";
<h1><code>DragGrid</code> Examples</h1>
<h2>Example 1</h2>
<p>
Grid with two programmatically blocked cells and one programmatically
blocked item
</p>
<h2>Example 2: "Tic-Tac-Toe"</h2>
<p>
A grid functioning as a playing field and another functioning as a
container for playing pieces. You can drag as many pieces as you want from
the container to the field.
</p>
<example2-tic-tac-toe></example2-tic-tac-toe>
<h2>Example 3: Counters</h2>
<p>
Showcasing local and global state: The local state of the counter
components doesn't change when moved inside one grid, but is cleared when
moved to the other. The global state is in the <code>data</code> attribute
of each item and gets transferred as well. Both grids have also custom
highlights.
</p>
<example3-counters></example3-counters>
<h2>Example 4: Dynamic lessons</h2>
<p>
These lessons are loaded from <code>computed</code> to simulate a
non-editable source like an API. they are changed using the method
<code>handleLessonMoved</code>. Try changing the sizes of Lesson1, the
grid and the texts of the items! The lesson container on the side doesn't
have a highlight and doesn't keep track of the item position. Try moving
<code>item3</code> back and forth!
</p>
<div>
<label>
Lesson 1 has length: {{ lesson1Length }}
<input
type="range"
v-model="lesson1Length"
min="1"
max="5"
step="1"
/>
</label>
<input type="text" v-model="lessonData.lesson1" />
</div>
<div>
<label>
Lesson grid has width: {{ lesson1Cols }}
<input type="range" v-model="lesson1Cols" min="2" max="5" step="1" />
</label>
<input type="text" v-model="lessonData.lesson2" />
</div>
<div>
<label>
Lesson grid has height: {{ lesson1Rows }}
<input type="range" v-model="lesson1Rows" min="6" max="10" step="1" />
<input type="text" v-model="lessonData.lesson3.inside" />
<input type="text" v-model="lessonData.lesson3.outside" />
</label>
</div>
<drag-grid
:value="lessons1"
:cols="parseInt(lesson1Cols)"
:rows="parseInt(lesson1Rows)"
class="bordered"
context="lesson"
@itemChanged="handleLessonMoved"
>
<template #item="item">
<div class="container">{{ item }}</div>
</template>
</drag-grid>
<drag-grid
:value="lessons1"
:cols="1"
:rows="10"
context="lesson"
grid-id="lesson-storage"
@itemChanged="handleLessonDropInContainer"
>
<template #item="item">
<div class="container">{{ item }}</div>
</template>
</drag-grid>
<h2>Example 5: Dynamic colors</h2>
<p>
This example showcases the <code>rawItem</code> with the custom method
<code>getColor</code>. Both grids on the outside call the method with
<code>"red"</code> while the one in the middle uses <code>"green"</code>.
We use arrays called <code>placedA</code>, <code>placedB</code> and
<code>placedC</code> to save, which item is contained in which grid.
Notice: the third grid doesn't save the item position, they are always
positioned automatically.
</p>
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<div class="ttt-container">
<drag-grid
:value="colorGrid"
:cols="4"
:rows="4"
grid-id="gridA"
context="colors"
class="bordered color-grid"
@itemChanged="handleColorItemChange"
>
<template #item="item">
<div
:style="{
background: item.rawItem.getColor('red'),
color: 'white',
}"
>
{{ item.data.name }}
</div>
</template>
</drag-grid>
<drag-grid
:value="colorGrid"
:cols="4"
:rows="4"
grid-id="gridB"
context="colors"
class="bordered color-grid"
@itemChanged="handleColorItemChange"
>
<template #item="item">
<div
:style="{
background: item.rawItem.getColor('green'),
color: 'black',
}"
>
{{ item.data.name }}
</div>
</template>
</drag-grid>
<drag-grid
:value="colorGrid"
:cols="4"
:rows="4"
grid-id="gridC"
context="colors"
class="bordered color-grid"
@itemChanged="handleColorItemChange"
>
<template #item="item">
<div
:style="{
background: item.rawItem.getColor('red'),
color: 'white',
}"
>
{{ item.data.name }}
</div>
</template>
</drag-grid>
</div>
<div class="ttt-container">
<div>
<h2>Example 6: Disabled grid</h2>
<p>
This uses the same data as the tic tac toe but is completely disabled.
Notice how the items still move if the tic tac toe grid above is
changed. Uncheck the checkbox to enable:
</p>
<label>
<input type="checkbox" v-model="gridDisabled" />
Grid disabled?
</label>
<drag-grid
:cols="3"
:rows="3"
:disabled="gridDisabled"
class="tic-tac-toe"
context="ticTacToe"
>
<template #item="item">
<CircularCard>
{{ item.key.startsWith("a") ? "X" : "O" }}
</CircularCard>
</template>
</drag-grid>
</div>
<div>
<h2>Example 7: Disabled fields and items with props</h2>
<p>
This is a grid with disabled fields and items. Red items are disabled
and cannot be moved.
</p>
<drag-grid
v-model="someDisabledItems"
:cols="4"
:rows="4"
class="tic-tac-toe"
:disabled-fields="disabledFields"
>
<template #item="{ rawItem }">
<div
class="container"
:style="{ background: rawItem.disabled ? 'red' : 'green' }"
></div>
</template>
<template #disabledField
><div class="container">This field is disabled!</div></template
>
</drag-grid>
<script>
export default {
name: "App",
methods: {
handleLessonMoved(lesson) {
this.logInput(lesson);
switch (lesson.key) {
case "lesson1":
this.lesson1X = lesson.x;
this.lesson1Y = lesson.y;
break;
case "lesson2":
this.lesson2X = lesson.x;
this.lesson2Y = lesson.y;
break;
case "lesson3":
this.lesson3X = lesson.x;
this.lesson3Y = lesson.y;
this.lesson3inPlan = true;
break;
default:
console.error("Something is wrong here!");
}
},
handleLessonDropInContainer(lesson) {
if (lesson.key === "lesson3") this.lesson3inPlan = false;
},
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
contains(array, search) {
return array.filter((obj) => obj === search).length > 0;
},
findAndRemove(array, element) {
let index = array.findIndex((i) => {
return i === element;
});
if (index >= 0) array.splice(index, 1);
},
handleColorItemChange(item) {
this[item.key].x = item.x;
this[item.key].y = item.y;
if (item.gridId === item.originGridId) return;
switch (item.gridId) {
case "gridA":
// Moved to gridA
this.findAndRemove(
item.originGridId === "gridB" ? this.placedB : this.placedC,
item.key
);
this.placedA.push(item.key);
break;
case "gridB":
// Moved to gridB
this.findAndRemove(
item.originGridId === "gridA" ? this.placedA : this.placedC,
item.key
);
this.placedB.push(item.key);
break;
case "gridC":
// Moved to gridC
this.findAndRemove(
item.originGridId === "gridB" ? this.placedB : this.placedA,
item.key
);
this.placedC.push(item.key);
break;
}
},
{ x: 1, y: 1, w: 1, h: 1, key: "a1", data: { text: "X" } },
{ x: 3, y: 3, w: 1, h: 1, key: "b1", data: { text: "O" } },
lesson1Length: 1,
lesson1Cols: 4,
lesson1Rows: 6,
lesson1X: 1,
lesson1Y: 1,
lesson2X: 2,
lesson2Y: 1,
lesson3X: -1,
lesson3Y: -1,
lesson3inPlan: false,
lessonData: {
lesson1: "Nothing",
lesson2: "Hallo",
lesson3: {
inside: "This is lesson 3 inside the plan",
outside: "This is lesson3 outside of the plan",
},
},
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
placedA: ["item1", "item2"],
placedB: ["item3", "item4"],
placedC: ["item5", "item6"],
item1: {
x: 1,
y: 1,
},
item2: {
x: 2,
y: 2,
},
item3: {
x: 1,
y: 1,
},
item4: {
x: 3,
y: 3,
},
item5: {
x: 2,
y: 4,
},
item6: {
x: 4,
y: 2,
},
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 },
],
disabledFields: [
{ x: 1, y: 1 },
{ x: 2, y: 3 },
],
computed: {
lessons1() {
return [
{
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,
},
return grid.gridId === "lesson-plan" ? this.lesson2X : 0;
},
y: (grid) => {
return grid.gridId === "lesson-plan" ? this.lesson2Y : 0;
},
w: 1,
h: parseInt(this.lesson1Length) + 1,
key: "lesson2",
data: {
text: this.lessonData.lesson2,
},
{
x: (grid) => {
if (this.lesson3inPlan) {
return grid.gridId === "lesson-plan" ? this.lesson3X : -1;
}
return grid.gridId === "lesson-plan" ? -1 : 0;
},
y: (grid) => {
if (this.lesson3inPlan) {
return grid.gridId === "lesson-plan" ? this.lesson3Y : -1;
}
return grid.gridId === "lesson-plan" ? -1 : 0;
},
w: 1,
h: parseInt(this.lesson1Length) + 1,
key: "lesson3",
data: (grid) => {
return {
text:
grid.gridId === "lesson-storage"
? this.lessonData.lesson3.outside
: this.lessonData.lesson3.inside,
};
},
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
colorGrid() {
let items = ["item1", "item2", "item3", "item4", "item5", "item6"];
let greens = [
"green",
"seagreen",
"greenyellow",
"darkolivegreen",
"limegreen",
"palegreen",
];
let reds = [
"darkred",
"indianred",
"orangered",
"red",
"maroon",
"firebrick",
];
return items.map((itemName) => {
return {
key: itemName,
x: (grid) => {
if (grid.gridId === "gridA") {
return this.contains(this.placedA, itemName)
? this[itemName].x
: -1;
} else if (grid.gridId === "gridB") {
return this.contains(this.placedB, itemName)
? this[itemName].x
: -1;
} else {
// gridC
return this.contains(this.placedC, itemName) ? 0 : -1;
}
},
y: (grid) => {
if (grid.gridId === "gridA") {
return this.contains(this.placedA, itemName)
? this[itemName].y
: -1;
} else if (grid.gridId === "gridB") {
return this.contains(this.placedB, itemName)
? this[itemName].y
: -1;
} else {
// gridC
return this.contains(this.placedC, itemName) ? 0 : -1;
}
},
w: 1,
h: 1,
data: {
name: itemName,
},
getColor: (a) =>
a === "red"
? reds[parseInt(itemName[4]) - 1]
: greens[parseInt(itemName[4]) - 1],
};
});
},
.container {
background: lightcoral;
width: 100%;
height: 100%;
}
.ttt-container {
display: flex;
justify-content: space-between;
}
.bordered {
border: 2px solid grey;
}
.color-grid {
min-height: 11em;
line-height: 2em;
box-sizing: content-box;
}
h2 {
padding-top: 1em;
}
h2 + p {
padding-bottom: 0.5em;
}
code {
background: lightgray;
padding: 0.2em;
border-radius: 3px;
}