Add components to canvas
authorJavier Sancho <jsf@jsancho.org>
Sat, 27 Mar 2021 19:15:53 +0000 (20:15 +0100)
committerJavier Sancho <jsf@jsancho.org>
Sat, 27 Mar 2021 19:15:53 +0000 (20:15 +0100)
src/App.vue
src/components/VDraggable.vue [new file with mode: 0644]
src/components/VSelector.vue [new file with mode: 0644]

index 0228dd397c4a34faaeb0ec102551dfc6bfd9ef07..be3e39e4309d6432502264c5d27bf12972ecb6bc 100644 (file)
       <router-link to="/">Home</router-link> |
       <router-link to="/about">About</router-link>
     </div>
+    <VSelector @select="addItem" />
+    <div>
+      <VDraggable v-for="(item, index) in items" :key="index">
+        <component :is="item.tag"></component>
+      </VDraggable>
+    </div>
+    <div
+      class="drop-zone"
+      @drop="onDrop($event, 1)"
+      @dragover.prevent
+      @dragenter.prevent
+    >
+      <div
+        v-for="item in listOne"
+        :key="item.title"
+        class="drag-el"
+        draggable
+        @dragstart="startDrag($event, item)"
+      >
+        {{ item.title }}
+      </div>
+    </div>
+    <div
+      class="drop-zone"
+      @drop="onDrop($event, 2)"
+      @dragover.prevent
+      @dragenter.prevent
+    >
+      <div
+        v-for="item in listTwo"
+        :key="item.title"
+        class="drag-el"
+        draggable
+        @dragstart="startDrag($event, item)"
+      >
+        {{ item.title }}
+      </div>
+    </div>
     <router-view />
   </div>
 </template>
 
+<script>
+import VDraggable from "@/components/VDraggable";
+import VSelector from "@/components/VSelector";
+
+export default {
+  components: {
+    VDraggable,
+    VSelector,
+  },
+  data() {
+    return {
+      items: [],
+      items2: [
+        {
+          id: 0,
+          title: "Item A",
+          list: 1,
+        },
+        {
+          id: 1,
+          title: "Item B",
+          list: 1,
+        },
+        {
+          id: 2,
+          title: "Item C",
+          list: 2,
+        },
+      ],
+    };
+  },
+  computed: {
+    listOne() {
+      return this.items2.filter((item) => item.list == 1);
+    },
+    listTwo() {
+      return this.items2.filter((item) => item.list == 2);
+    },
+  },
+  methods: {
+    startDrag(evt, item) {
+      evt.dataTransfer.dropEffect = "move";
+      evt.dataTransfer.effectAllowed = "move";
+      evt.dataTransfer.setData("itemID", item.id);
+    },
+    onDrop(evt, list) {
+      const itemID = evt.dataTransfer.getData("itemID");
+      const item = this.items2.find((item) => item.id == itemID);
+      item.list = list;
+    },
+    addItem(tag) {
+      this.items.push({ tag: tag });
+    },
+  },
+};
+</script>
+
 <style lang="scss">
 #app {
   font-family: Avenir, Helvetica, Arial, sans-serif;
     }
   }
 }
+
+.drop-zone {
+  background-color: #eee;
+  margin-bottom: 10px;
+  padding: 10px;
+}
+
+.drag-el {
+  background-color: #fff;
+  margin-bottom: 10px;
+  padding: 5px;
+}
 </style>
diff --git a/src/components/VDraggable.vue b/src/components/VDraggable.vue
new file mode 100644 (file)
index 0000000..132c287
--- /dev/null
@@ -0,0 +1,11 @@
+<template>
+  <div>
+    <slot></slot>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "VDraggable",
+};
+</script>
diff --git a/src/components/VSelector.vue b/src/components/VSelector.vue
new file mode 100644 (file)
index 0000000..545c99f
--- /dev/null
@@ -0,0 +1,40 @@
+<template>
+  <b-button-group>
+    <b-button
+      v-for="(item, index) in items"
+      :key="index"
+      @click="selectItem(item.tag)"
+    >
+      {{ item.caption }}
+    </b-button>
+  </b-button-group>
+</template>
+
+<script>
+export default {
+  name: "VSelector",
+  data() {
+    return {
+      items: [
+        {
+          tag: "b-form-input",
+          caption: "Form Input",
+        },
+        {
+          tag: "b-form-radio",
+          caption: "Form Radio",
+        },
+        {
+          tag: "b-form-select",
+          caption: "Form Select",
+        },
+      ],
+    };
+  },
+  methods: {
+    selectItem(tag) {
+      this.$emit("select", tag);
+    },
+  },
+};
+</script>