From c239cfbcccbaac618fa0f4387432f73a903ca01b Mon Sep 17 00:00:00 2001 From: Julian Leucker <leuckerj@gmail.com> Date: Thu, 9 Feb 2023 13:05:11 +0100 Subject: [PATCH] Accept functions for own properties --- example/src/App.vue | 77 +++++++++++++++++++++++++++++++++++++++++++++ src/DragGrid.vue | 43 +++++++++++++++++-------- 2 files changed, 107 insertions(+), 13 deletions(-) diff --git a/example/src/App.vue b/example/src/App.vue index e9a35c4..5750f67 100644 --- a/example/src/App.vue +++ b/example/src/App.vue @@ -70,6 +70,33 @@ import NumberCounter from "./components/NumberCounter.vue"; </template> </drag-grid> </div> + <div class="ttt-container"> + <label> + Lesson 1 has length: {{ lesson1Length }} + <input type="range" v-model="lesson1Length" min="1" max="5" step="1" /> + </label> + <label> + Lesson grid has width: {{ lesson1Cols }} + <input type="range" v-model="lesson1Cols" min="2" max="5" step="1" /> + </label> + <label> + Lesson grid has height: {{ lesson1Rows }} + <input type="range" v-model="lesson1Rows" min="6" max="10" step="1" /> + </label> + + <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> + </div> </div> </template> @@ -93,6 +120,21 @@ export default { logInput(input) { console.log("New movement detected:", input); }, + 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; + default: + console.error("Something is wrong here!"); + } + }, }, data() { return { @@ -131,8 +173,39 @@ export default { { x: 1, y: 2, w: 1, h: 1, key: "d", data: { num: 30 } }, { x: 3, y: 1, w: 1, h: 1, key: "e", data: { num: 3 } }, ], + lesson1Length: 1, + lesson1Cols: 4, + lesson1Rows: 6, + lesson1X: 1, + lesson1Y: 1, + lesson2X: 2, + lesson2Y: 1, }; }, + computed: { + lessons1() { + return [ + { + x: this.lesson1X, + y: this.lesson1Y, + w: 1, + h: this.lesson1Length, + key: "lesson1", + data: {}, + }, + { + x: (grid) => { + return grid.context === "lesson" ? this.lesson2X : 1; + }, + y: this.lesson2Y, + w: 1, + h: parseInt(this.lesson1Length) + 1, + key: "lesson2", + data: {}, + }, + ]; + }, + }, }; </script> @@ -171,4 +244,8 @@ export default { display: flex; justify-content: space-between; } + +.bordered { + border: 2px solid grey; +} </style> diff --git a/src/DragGrid.vue b/src/DragGrid.vue index 2882c87..93096c9 100644 --- a/src/DragGrid.vue +++ b/src/DragGrid.vue @@ -11,10 +11,10 @@ v-for="item in value" :key="item.key" :drag-i-d="item.key" - :x="item.x" - :y="item.y" - :w="item.w" - :h="item.h" + :x="get('x', item)" + :y="get('y', item)" + :w="get('w', item)" + :h="get('h', item)" :data="item.data" :context="context" > @@ -44,7 +44,7 @@ export default { components: { DragContainer, }, - emits: ["input"], + emits: ["input", "itemChanged"], props: { rows: { type: Number, @@ -145,17 +145,30 @@ export default { if (!newPositionValid) return; - let valueCopy = structuredClone(this.value); - - let index = valueCopy.findIndex((i) => { - return i.key === element.key; - }); - if (index >= 0) valueCopy.splice(index, 1); + try { + let valueCopy = structuredClone(this.value); + + let index = valueCopy.findIndex((i) => { + return i.key === element.key; + }); + if (index >= 0) valueCopy.splice(index, 1); + + valueCopy.push(element); + this.$emit("input", valueCopy); + } catch (e) { + if (e.code === DOMException.DATA_CLONE_ERR) { + // We use functions for properties → we can't clone; only emit `item-changed` event + console.debug( + "Grid couldn't be cloned, please listen to the `item-changed` event and handle changes yourself." + ); + } else { + throw e; + } + } element.x = coords.x; element.y = coords.y; - valueCopy.push(element); - this.$emit("input", valueCopy); + this.$emit("itemChanged", element); }, getCoords(x, y) { return { @@ -163,6 +176,10 @@ export default { y: Math.ceil(y / (this.$el.offsetHeight / this.rows)), }; }, + get(property, item) { + let val = item[property] || 1; + return val instanceof Function ? val(this) : parseInt(val); + }, }, }; </script> -- GitLab