Hi i'm able to swap or order within a section very easily
But i'm failing to swap between 2 sections i,e from leftSection to rightSection as shown in image
Here is full code
https://codesandbox.io/s/peaceful-almeida-mbw2m?file=/src/App.vue
within leftSection i'm doing like this
leftSection: [
{ Name: "L - A", order: 1 },
{ Name: "L - B", order: 2 },
{ Name: "L - C", order: 3 },
]
<draggable
v-model="leftSection"
group="section"
#start="drag = true"
#end="drag = false"
>
<div v-for="section in leftSection" :key="section.Name" class="card">
{{ section.Name }}
</div>
</draggable>
in similar way i'm doing for within rightSection but don't know how to swap between 2 sections.
please help me thanks in advance..!!!
use a single object and dynamically output it to a component
It might look something like this:
<div class="section-wrapper">
<draggable v-model="sections" group="sections">
<div
v-for="(item, index) of sections"
:key="index"
class="section-column"
>
<draggable
v-model="sections[index].fields"
group="{name: 'fields-' + index}"
>
<div
v-for="(section, index) in item.fields"
:key="index"
class="card"
>
{{ section.Name }}
</div>
</draggable>
</div>
</draggable>
</div>
<div class="display-section">
<div v-for="left in sections[0].fields" :key="left.Name">
{{ left.Name }}
</div>
<hr />
<div v-for="right in sections[1].fields" :key="right.Name">
{{ right.Name }}
</div>
</div>
...
sections: [
{
fields: [
{ Name: "L - A", order: 1 },
{ Name: "L - B", order: 2 },
{ Name: "L - C", order: 3 },
],
order: 1,
},
{
fields: [
{ Name: "R - A", order: 1 },
{ Name: "R - B", order: 2 },
],
order: 2,
},
],
...
Code template: sandbox link
However, one point should be taken into account. Since both columns are wrapped in a common draggable, elements can be moved between columns.
Related
here's my problem :
I'm using the VueDraggable library in order to drag and drop elements between a DragBoard.vue and a DropBoard.vue, and a specific type of element should allow to be nested when it is in the DropBoard.
I'm going to take this element as an example :
"Grouped Items"
To do that I've followed this example : https://github.com/SortableJS/vue.draggable.next/blob/master/example/components/nested-example.vue
And this is what I get when I drop "Grouped Items" into the DropBoard.vue :
IMG
As you can see, the DropBoard appears a second time inside Grouped items for whatever reason. I've supposed that the nested-draggable tag also loop what is out of the draggable tag and I've no idea how to resolve that...
📄 dragItems.JSON (used in DragBoard.vue) :
1st object is a common element
2nd object is a nestable element
[
{
"type": "Simple list",
"title": "Simple list",
"id": 1,
"properties": "this is an item property"
},
...
{
"type": "Grouped items",
"title": "Grouped items",
"id": 10,
"properties": "this is an item property",
"tasks": []
},
...
]
🚩 DropBoard.vue template:
<template>
<div class="board">
<div class="head">Mock</div>
<div class="dd-container">
<draggable
:list="tasks"
v-model="dropItems"
item-key="title"
:group="{ name: 'items', put: true }"
#change="log"
>
<template #item="{ element }">
<div
class="item"
:key="element"
>
<div>
{{ element.title }}
</div>
<nested-draggable
v-if="element.tasks"
:tasks="element.tasks"
class="group-container"
/>
<div class="trashico" :key="index">
<i class="fas fa-trash" #click="deleteItem(index)"></i>
</div>
</div>
</template>
</draggable>
</div>
</div>
</template>
🚩 DropBoard.vue script
<script>
import draggable from "vuedraggable";
export default {
name: "nested-draggable",
components: {
draggable,
},
props: {
dropItems: {
type: Array,
required: true,
},
tasks: {
required: true,
type: Array,
},
},
data() {
return {
dropItems: [],
};
},
methods: {
deleteItem(id) {
this.dropItems.splice(id, 1);
},
},
};
</script>
Here is what I found while using the Vue DevTools, it's quit explicit about the problem.
See image: IMG
<div class="col-3" v-for="n in 5" :key="n">
<h3>Table {{n}}</h3>
<draggable class="list-group" :list="`list${n}`" group="people" #change="log">
<div
class="list-group-item"
v-for="`(element, index) in list${n}`"
:key="element.name"
>
{{ element.name }} {{ index }}
</div>
</draggable>
</div>
Why can't I set the v-for or :list as a concatenated string? Is there any way around this?
Full code:
<template>
<div class="row">
<component
v-for="(component, index) in components"
:key="index"
:is="component"
/>
<div class="col-3" v-for="n in listNumber" :key="n">
<h3>Table {{n}}</h3>
<draggable class="list-group" :list="list${n}" group="people" #change="log">
<div
class="list-group-item"
v-for="(element, index) in list${n}"
:key="element.name"
>
{{ element.name }} {{ index }}
</div>
</draggable>
</div>
</div>
</template>
<script>
import draggable from "vuedraggable";
let id = 1;
export default {
name: "two-lists",
display: "Two Lists",
order: 1,
components: {
draggable,
list:[],
},
data() {
return {
list1: [
{ name: "John", id: 1 },
{ name: "Joao", id: 2 },
{ name: "Jean", id: 3 },
{ name: "Gerard", id: 4 }
]
},
{
list2: [
{ name: "Juan", id: 5 },
{ name: "Edgard", id: 6 },
{ name: "Johnson", id: 7 }
],
listNumber: 3,
}
},
created(){
console.log(this.list);
},
methods: {
add: function() {
this.list.push({ name: "Juan" });
},
replace: function() {
this.list = [{ name: "Edgard" }];
},
clone: function(el) {
return {
name: el.name + " cloned"
};
},
}
};
</script>
It's a bit difficult to understand exactly what you're trying to do but it looks like you're trying to get a specific list in the v-for loop.
One way to fix your issue would be to nest your lists inside of an object in your data like this:
data() {
return {
listNumber: 3,
lists: {
list1: [
{ name: "John", id: 1 },
{ name: "Joao", id: 2 },
{ name: "Jean", id: 3 },
{ name: "Gerard", id: 4 }
],
list2: [
{ name: "Juan", id: 5 },
{ name: "Edgard", id: 6 },
{ name: "Johnson", id: 7 }
],
},
};
And then in your code you can just do lists[`list${n}`] like this:
<div class="col-3" v-for="n in listNumber" :key="n">
<h3>Table {{n}}</h3>
<draggable class="list-group" :list="lists[`list${n}`]" group="people" #change="log">
<div
class="list-group-item"
v-for="(element, index) in lists[`list${n}`]"
:key="element.name"
>
{{ element.name }} {{ index }}
</div>
There is a lot more refactoring and other cleanup you could (and should) probably do but this should at least get you over this hurdle.
I have the following:
<div v-for="num in [1,2,3,4,5]" :key="num ">
<customelement0 :num ="num" />
<span #click="show = !show" > Details: </span>
<customelement1 v-if="show" :num ="num" />
<hr />
</div>
and:
export default {
data() {
return {
show: false
};
},
};
However, in this implementation Whenever show changes it affects all of the customelement1s and will show/hide all of them.
How would one solve this problem, so that whenever a user clicks on the span it only shows/hides one element in the loop?
P.S.: in reality, the length of the loop is much longer, than what's indicated above
The problem here is essentially that your show is a variable for the entire component, and isn't linked to one of your array elements.
Generally, we don't really tend to hard-code an array into the html, but rather in the data, as shown in the other answers.
The other answers show it with num being coded into the object but you could also do something like this. Note that other field is optional and not required. The main advantage of this method is that you don't need to code every number.
<div v-for="(item, i) in items" :key="i">
<!-- Note I do i+1 so that it matches the 1,2,3 in your example -->
<!-- if you're okay with having 0,1,2 you can omit the +1 -->
<customelement0 :num="i+1" />
<span #click="item.show = !item.show" >Details: </span>
<customelement1 v-if="item.show" :num="i+1" />
<hr />
</div>
export default {
data() {
return {
items: [
{show: false, other: "foo"},
{show: false, other: "bar"},
//...
],
};
},
};
You can change number to object and toggle property:
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="todo in todos">
<label>
<input type="checkbox"
v-on:change="toggle(todo)"
v-bind:checked="todo.done">
<del v-if="todo.done">
{{ todo.text }}
</del>
<span v-else>
{{ todo.text }}
</span>
</label>
</li>
</ol>
</div>
new Vue({
el: "#app",
data: {
todos: [
{ text: "1", done: false },
{ text: "2", done: false },
{ text: "3", done: true },
{ text: "4", done: true },
{ text: "5", done: true },
]
},
methods: {
toggle: function(todo){
todo.done = !todo.done
}
}
})
You can to save the value isShow for each element in the array. So you need to use an array of objects in you data and do something like this:
export default {
data() {
return {
numList: [
{
num: 1,
isShow: true
},
{
num: 2,
isShow: true
}
]
};
},
};
In your template:
<div v-for="item in numList" :key="item.num">
<customelement0 :num="item.num" />
<span #click="item.isShow = !item.isShow" > Details: </span>
<customelement1 v-if="item.isShow" :num="item.num" />
<hr />
</div>
I have created loops for some v-select. When I enter v-model it makes my v-select the same value. How i can fix this?
<template>
<div class="create-group">
<div class="form-group">
<button class="btn btn-defualt addGroup" v-on:click="addmember(member.value)">
<h3>Crate Group</h3>
</button>
<div class="member">
<div class="row">
<div class="col-lg-2" style="padding-right: 0;">
<h3>member in grroup :</h3>
{{member}}
</div>
<div class="col-lg-10 list" v-bind:class="{'list-member' : listActive}">
<div class="input-member" v-for="list in lists" v-bind:key="list.id">
<h3>{{list.count}}.</h3>
<div class="select">
<v-select :options="options" v-model="member"></v-select>
</div>
</div>
<div class="add-member" v-on:click="add()">
<h4>+ add member</h4>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
My data:
data() {
return {
member: [],
newitem: { name: "", type: [] },
options: [],
lists: [{ count: "1" }, { count: "2" }, { count: "3" }],
};
},
You are assigning selected value to member that is the same between all selectors. You need to use different variables for different lists, like this:
<v-select :options="options" v-model="member[list.id]"></v-select>
data() {
return {
member: {}, // <- This is object now
newitem: { name: "", type: [] },
options: [],
lists: [{ count: "1" }, { count: "2" }, { count: "3" }],
};
},
I am using the following library
https://sortablejs.github.io/Vue.Draggable/#/custom-clone
specifically using the example:
https://github.com/SortableJS/Vue.Draggable/blob/master/example/components/clone-on-control.vue
<template>
<v-container fluid>
<div class="row">
<div class="col-3">
<h3>Draggable 1</h3>
<draggable
class="row wrap fill-height align-center sortable-list"
style="background: red;"
:list="list1"
:group="{ name: 'people', pull: pullFunction }"
#start="start"
>
<v-card class="list-group-item" v-for="element in list1" :key="element.id">
{{ element.name }}
</v-card>
</draggable>
</div>
<div class="col-3">
<h3>Draggable 2</h3>
<draggable class="dragArea list-group" :list="list2" group="people">
<v-card class="list-group-item" v-for="element in list2" :key="element.id">
{{ element.name }}
</v-card>
</draggable>
</div>
</div>
</template>
<script>
import draggable from "vuedraggable";
export default {
components: {
draggable
},
data(){
return {
list1: [
{ name: "Jesus", id: 1 },
{ name: "Paul", id: 2 },
{ name: "Peter", id: 3 }
],
list2: [
{ name: "Luc", id: 5 },
{ name: "Thomas", id: 6 },
{ name: "John", id: 7 }
],
controlOnStart: true
}
},
methods:{
pullFunction() {
return this.controlOnStart ? "clone" : true;
},
start({ originalEvent }) {
this.controlOnStart = originalEvent.ctrlKey;
}
}
}
</script>
What I need to do is fill only a list, that is, from Draggable 1 to Draggable 2, currently it is from Draggable 1 to Draggable 2 and from Draggable 2 to Draggable 1 but I don't need it that way.
Thank you