I'm using UIKit (GetUIKit) within Vue.js. I have 3 lists of objects (id, picture) that I drag across. I would like to save the position of the pictures in each list but the arrays don't seem to have changed and I don't know how to find which array it has be dropped into.
<template>
<div class="uk-child-width-1-4#s" uk-grid>
<div>
<h4>Selected products</h4>
<div
uk-sortable="group: sortable-group"
v-for="product in selectedProducts"
v-bind:key="product.id"
v-on:stop="greet(product.id, selectedProducts, outfit1, outfit2)"
>
<div class="uk-card uk-card-small uk-card-default uk-card-body">
<img v-bind:src="product.image">
</div>
</div>
</div>
<div>
<h4>Outfit 1</h4>
<div
uk-sortable="group: sortable-group"
v-for="product in outfit1"
v-bind:key="product.id"
v-on:stop="greet(product.id, selectedProducts, outfit1, outfit2)
>
<div class="uk-card uk-card-small uk-card-default uk-card-body">
<img v-bind:src="product.image">
</div>
</div>
</div>
<div>
<h4>Outfit 2</h4>
<div
uk-sortable="group: sortable-group"
v-for="product in outfit2"
v-bind:key="product.id"
v-on:stop="greet(product.id, selectedProducts, outfit1, outfit2)"
>
<div class="uk-card uk-card-small uk-card-default uk-card-body">
<img v-bind:src="product.image">
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
selectedProducts: [
{
id: 1,
name: "Cool top",
image:
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTfpwfhIA_q8BvD5Hj6TKHfTd0fhfaNQcYKPlBcww6aZXWUOE3R"
},
{
id: 2,
name: "Fun jeans",
image:
"https://wwws.dior.com/couture/ecommerce/media/catalog/product/cache/1/grid_image_8/460x497/17f82f742ffe127f42dca9de82fb58b1/U/d/1550571393_922P02A3932_X5846_E08_GH.jpg"
}
],
outfit1: [
{
id: 3,
name: "shoes",
image: "https://images.vans.com/is/image/Vans/D3HY28-HERO?$583x583$"
}
],
outfit2: [
{
id: 4,
name: "scarf",
image:
"https://www.brontebymoon.co.uk/wp-content/uploads/2017/04/TAR80-A01-Lambswool-Tartan-Scarf-Antique-Dress-Stewart.jpg"
}
]
};
},
methods: {
greet: function(position, ) {
// This is where I want to save the position, for ex: {outfit1: [id: 1,2], outfit2: [id: 3], selectedProduct: [id: 4]}
console.log(position);
}
}
};
</script>
I want to save the position, for ex: {outfit1: [id: 1,2], outfit2: [id: 3], selectedProduct: [id: 4]} but I'm stuck. Any ideas?
Thank you!
Related
I'm new at vue3 and javascript. I have 2 lists and drag and drop system. The problem is when I drag and drop component from one list to another, I increase an id by 1, but I can't get the name of dragged object and display it. The problem displayed at methods in method "cloneComponent"
<template>
<div class="full-zone">
<div class="components">
<h3>Компоненты бота:</h3>
<draggable
class="dragArea"
:list="list1"
:group="{ name: 'people', pull: 'clone', put: false }"
:clone="cloneComponent"
#change="log"
item-key="id"
>
<template #item="{element}">
<div class="list-group-item">
{{ element.name }}
</div>
</template>
</draggable>
</div>
<div class="constructor">
<h3>Конструктор</h3>
<draggable
class="constructor-list"
:list="list2"
group="people"
#change="log"
item-key="id"
>
<template #item="{ element, index }">
<div class="list-group-item">
{{ element.name }}
<div>
<input type="text" class="input" v-model="element.text" placeholder="Введите текст компонента" />
<span #click="remove(index)" class="remove">x</span>
</div>
</div>
</template>
</draggable>
</div>
<div>
<button class="btn">Сгенерировать бота</button>
</div>
<rawDisplayer class="col-3" :value="list1" title="List 1" />
<rawDisplayer class="col-3" :value="list2" title="List 2" />
</div>
</template>
<script>
import draggable from "vuedraggable";
let idGlobal = 4;
export default {
name: "clone",
display: "Clone",
order: 2,
components: {
draggable
},
data() {
return {
list1: [
{ name: "Сообщение", text: "", id: 1 },
{ name: "Заметка", text: "", id: 2 },
{ name: "Кнопка", text: "", id: 3 },
],
list2: []
};
},
methods: {
log: function(evt) {
window.console.log(evt);
},
cloneComponent() {
return {
id: idGlobal ++,
}
},
remove(idx) {
this.list2.splice(idx, 1);
},
}
};
</script>
How to return not only "id", but "name" at the same time? Please help.
You need to send the item to the other list
// tolist = can be 1 or 2
cloneComponent(item, tolist) {
if (tolist === 2) {
this.list2.push(item)
} else {
this.list1.push(item)
}
}
I'm completely new to VueJS and am trying to create a project tile list with different data values per tile. I use Vue CLI. I created a component which is my template for one project tile.
component TheProjectTile.vue :
<template>
<router-link to="{{ project.url }}">
<div
class="row project-container"
style="background-color: {{ project.backgroundcolor }};"
v-scrollanimation
>
<div class="column column-60">
<h2>{{ project.title }}</h2>
<div class="button">view</div>
</div>
<div class="column">
<img src="#/assets/img/{{ project.image }}" alt="{{ project.title }}" />
</div>
</div>
</router-link>
</template>
<script type="text/javascript">
export default {
props: { project: Object },
data() {
return {}
}
}
</script>
Then I have my View on my Vue CLI application where I want to render the project tiles and where I want to give the data to the tiles:
View where the projects should be shown
<template>
<div id="projekte">
<section class="container">
<div id="projects">
<projectlist v-for="project in projects" :project="project" />
</div>
</section>
</div>
</template>
<script>
import TheProjectTile from './components/TheProjectTile'
export default {
components: {
projectlist: TheProjectTile
},
data() {
return {
projects: [
{
url: '/projekte/client1',
backgroundcolor: '#005ca9',
title: 'Website client 1',
img: 'client1.png'
},
{
url: '/projekte/client2',
backgroundcolor: '#c10b25',
title: 'Website client 2',
img: 'client2.png'
}
]
}
}
}
</script>
What do I need to change that it works? :/
Please take a look at following snippet:
You need to bind data with v-bind or :,
in v-for loop you need key
Vue.component('projectList', {
template: `
<a :to="project.url">
<div
class="row project-container"
:style="{'background-color': project.backgroundcolor}"
>
<div class="column column-60">
<h2>{{ project.title }}</h2>
<div class="button">view</div>
</div>
<div class="column">
<img :src="'#/assets/img/'+project.image" :alt="project.title" />
</div>
</div>
</a>
`,
props: { project: Object },
})
new Vue({
el: '#demo',
data() {
return {
projects: [{url: '/projekte/client1', backgroundcolor: '#005ca9', title: 'Website client 1', img: 'client1.png'}, {url: '/projekte/client2', backgroundcolor: '#c10b25', title: 'Website client 2', img: 'client2.png'}]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div id="projekte">
<section class="container">
<div id="projects">
<!-- 👇 key -->
<project-list v-for="(project, index) in projects" :key="index" :project="project" />
</div>
</section>
</div>
</div>
This is my data, initially I want show only 4 albums on the page, then when a user click on Show More I want to load the next 4 albums. And when user click on the Show Less button, it goes back to the previous/initial state.
cardData: [
{
id: 1,
img: eight0eightheartbreak,
title: '808 & Heartbreak',
desc: 'desc 1'
},
{
id: 2,
img: collegedropout,
title: 'College Dropout',
desc: 'desc 2'
},
{
id: 3,
img: graduation,
title: 'Graduation',
desc: 'desc 3'
},
{
id: 4,
img: lateregistration,
title: 'Late Registration',
desc: 'desc 4'
},
{
id: 5,
img: MBDTF,
title: 'My Beatiful Dark Twisted Fantesy',
desc: 'desc 5'
},
{
id: 6,
img: TLOP,
title: 'The Life of Pablo',
desc: 'desc 6'
},
{
id: 7,
img: Ye,
title: 'Ye',
desc: 'desc 7'
},
{
id: 8,
img: yeezus,
title: 'Yeezus',
desc: 'desc 8'
},
{
id: 9,
img: JIK,
title: 'Jesus Is King',
desc: 'desc 9'
}
]
}
this is my code
const [readMore, setReadMore] = useState(false);
const [noOfElements, setnoOfElements] = useState(4);
const slice = Data.cardData.slice(0, noOfElements);
const loadMore = ()=>{
setnoOfElements(noOfElements + 4)
}
return (
<section className="py-4 container">
<div className="row justify-content-center">
{slice.map((item, index)=>{
return(
<div className= "col-11 col-md-6 col-lg-3 max-0 mb-4">
<div className="card p-0 overflow-hidden h-100 shadow">
<img src={item.img} alt="" className="card-img-top" />
<div className="card-body">
<h5 className="card-title">{item.title}</h5>
<p className="card-text">{item.desc}</p>
</div>
</div>
</div>
)
})}
</div>
<button className="btn btn-dark d-block-w-100" onClick={()=>loadMore()} >
Read more
</button>
</section>
)
}
I have managed to create a Show more button, now how do I create Show Less button using the same logic, react useState hook? I know how to make it using component, but I want to do it using useState, is there anyway I can do it?
You can just put a conditional tag in your slice.map:
{slice.map((item, index)=>{
if( index <= noOfElements ){
return <div className= "col-11 col-md-6 col-lg-3 max-0 mb-4">...</div>
}
}
const [readMore, setReadMore] = useState(false);
const [noOfElements, setnoOfElements] = useState(4);
const slice = Data.cardData.slice(0, noOfElements);
const loadMore = ()=>{
setnoOfElements(noOfElements + 4)
}
const loadLess = ()=>{
setnoOfElements(noOfElements - 4)
}
return (
<section className="py-4 container">
<div className="row justify-content-center">
{slice.map((item, index)=>{
return(
<div className= "col-11 col-md-6 col-lg-3 max-0 mb-4">
<div className="card p-0 overflow-hidden h-100 shadow">
<img src={item.img} alt="" className="card-img-top" />
<div className="card-body">
<h5 className="card-title">{item.title}</h5>
<p className="card-text">{item.desc}</p>
</div>
</div>
</div>
)
})}
</div>
<button className="btn btn-dark d-block-w-100" onClick={()=>loadMore()} >
Read more
</button>
<button className="btn btn-dark d-block-w-100" onClick={()=>loadLess()} >
Read less
</button>
</section>
)
Is this is you actually needed?
I have a list of people when clicking on them is marked with a red border, I also have two buttons, I want to make it so that when one of these buttons is pressed, the red border disappears, that is, cancel the active class, since when one of these people is clicked, it is activated a class named selectAvatarBorder
You can also see the given code in codesandbox
<template>
<div>
<div class="avatars-mob-container">
<div class="avatars-container">
<div class="av-row">
<div
v-for="(chunk, index) in Math.ceil(usersGroup.length / 2)"
:key="index"
>
<div
v-for="(user, index) in usersGroup.slice(
(chunk - 1) * 2,
chunk * 2
)"
:key="index"
class="avatar-columns"
:class="{ selectAvatarBorder: selectedUsers === user.id }"
#click="setUserBorderColor(user.id)"
>
<div>
<img width="100" height="100" :src="user.img" alt="avatar" />
</div>
<div>
<p class="avatar-name">{{ user.name }} {{ index }}</p>
</div>
</div>
</div>
</div>
</div>
<div class="users-btn-group">
<div style="margin-right: 10px">
<button
:class="{
firstBtnMobUsersColor: state === 1,
secondBtnMobUsersColor: state === 2,
}"
#click="setState(1)"
>
Other
</button>
</div>
<div>
<button
:class="{
firstBtnMobUsersColor: state === 2,
secondBtnMobUsersColor: state === 1,
}"
#click="setState(2)"
>
Open to All
</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
methods: {
setState(s) {
this.state = s;
},
setUserBorderColor(s) {
this.selectedUsers = s;
},
},
data() {
return {
state: 0,
selectedUsers: 0,
usersGroup: [
{
id: 1,
name: "American Indian",
img:
"http://astragem.com/static/images/ClickSearchComponent/users/1.png",
},
{
id: 2,
name: "Black/African Descent",
img:
"http://astragem.com/static/images/ClickSearchComponent/users/2.png",
},
{
id: 3,
name: "Hispanic/Latino",
img:
"http://astragem.com/static/images/ClickSearchComponent/users/3.png",
},
{
id: 4,
name: "White Caucasian",
img:
"http://astragem.com/static/images/ClickSearchComponent/users/4.png",
},
],
};
},
};
</script>
<style scoped>
.selectAvatarBorder {
border: 2px solid #CC003D !important;
border-radius: 16px;
}
.firstBtnMobUsersColor {
background: #CC003D !important;
color: white !important;
}
.secondBtnMobUsersColor {
background: white !important;
color: red !important;
}
</style>
Something like this?
<template>
<div>
<div class="avatars-mob-container">
<div class="avatars-container">
<div class="av-row">
<div
v-for="(chunk, index) in Math.ceil(usersGroup.length / 2)"
:key="index"
>
<div
v-for="(user, index) in usersGroup.slice(
(chunk - 1) * 2,
chunk * 2
)"
:key="index"
class="avatar-columns"
:class="{ selectAvatarBorder: selectedUsers === user.id && isSelected }"
#click="setUserBorderColor(user.id)"
>
<div>
<img width="100" height="100" :src="user.img" alt="avatar" />
</div>
<div>
<p class="avatar-name">{{ user.name }} {{ index }}</p>
</div>
</div>
</div>
</div>
</div>
<div class="users-btn-group">
<div style="margin-right: 10px">
<button
:class="{
firstBtnMobUsersColor: state === 1,
secondBtnMobUsersColor: state === 2,
}"
#click="setState(1)"
>
Other
</button>
</div>
<div>
<button
:class="{
firstBtnMobUsersColor: state === 2,
secondBtnMobUsersColor: state === 1,
}"
#click="setState(2)"
>
Open to All
</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
methods: {
setState(s) {
this.state = s;
this.isSelected = false;
},
setUserBorderColor(s) {
this.selectedUsers = s;
this.isSelected = true;
},
},
data() {
return {
state: 0,
selectedUsers: 0,
isSelected: false,
usersGroup: [
{
id: 1,
name: "American Indian",
img:
"http://astragem.com/static/images/ClickSearchComponent/users/1.png",
},
{
id: 2,
name: "Black/African Descent",
img:
"http://astragem.com/static/images/ClickSearchComponent/users/2.png",
},
{
id: 3,
name: "Hispanic/Latino",
img:
"http://astragem.com/static/images/ClickSearchComponent/users/3.png",
},
{
id: 4,
name: "White Caucasian",
img:
"http://astragem.com/static/images/ClickSearchComponent/users/4.png",
},
],
};
},
};
</script>
As when you are clicking on image you are setting an index in the selectedUsers, so just add this.selectedUsers = 0; in the setState function.
I need a help for vuedraggable component. I have three columns. (Photo inserted) I want to drag BoardUserCard between columns and want to send PUT request to database for changing "lead_status_id" related to column dropped. How can I achieve this ? I can not find any example about apis in documentation.
<template>
<div class="board">
<div class="boards">
<div class="boards-cards leads">
<div class="board-card-header ">
<h3>
Leads
</h3>
<span>
{{ allLeads.length }}
</span>
</div>
<draggable
ghost-class="ghost"
:list="allLeads"
class="board-card-body"
:options = "{group:allLeads}"
group="leads"
#change="handleChange"
>
<BoardUserCard
v-for="item in allLeads"
:key="item.name"
:name="item.name"
:email="item.email"
:img="item.img"
:status="item.status"
/>
</draggable>
</div>
<div class="boards-cards contacted">
<div class="board-card-header ">
<h3>
Contacted
</h3>
<span>
{{ contactedLeads.length }}
</span>
</div>
<draggable
ghost-class="ghost"
:list="contactedLeads"
class="board-card-body"
:options = "{group:contactedLeads}"
group="leads"
#change="handleChange"
>
<BoardUserCard
v-for="item in contactedLeads"
:key="item.name"
:name="item.name"
:email="item.email"
:img="item.img"
:status="item.status"
/>
</draggable>
</div>
<div class="boards-cards converted">
<div class="board-card-header ">
<h3>
Converted
</h3>
<span>
{{ convertedLeads.length }}
</span>
</div>
<draggable
ghost-class="ghost"
:list="convertedLeads"
class="board-card-body"
:options = "{group:convertedLeads}"
group="leads"
#change="handleChange"
>
<BoardUserCard
v-for="item in convertedLeads"
:key="item.name"
:name="item.name"
:email="item.email"
:img="item.img"
:status="item.status"
/>
</draggable>
</div>
</div>
</div>
</template>
<script>
import BoardUserCard from "#/components/BoardUserCard.vue";
import draggable from "vuedraggable";
export default {
name: "Dashboard",
components: {
BoardUserCard,
draggable,
},
data() {
return {
showModal: false,
allLeads: [
{
name: "Richard",
email: "Richard#gmail.com",
img: "avatar-small.svg",
status: "all"
},
{ name: "Rachael", email: "Rachael#gmail.com", img: "leads.svg", status: "all" },
{ name: "Matt", email: "Matt#gmail.com", img: "user-avatar.svg",status: "all" },
{ name: "Brad", email: "Brad#gmail.com", img: "leads.svg", status: "all"},
],
contactedLeads: [
{
name: "Jeniffer",
email: "Jeniffer#gmail.com",
img: "avatar-small.svg",
status: "contacted"
},
],
convertedLeads: [
{ name: "Mike", email: "Mike#gmail.com", img: "leads.svg", status: "converted" },
],
};
},
methods: {
openModal() {
this.showModal = true;
},
closeModal() {
this.showModal = false;
},
handleChange(event){
console.log(event)
}
},
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
All I need to add data attribute in component data-id="4"
<draggable
ghost-class="ghost"
:list="convertedLeads"
class="board-card-body"
:options = "{group:convertedLeads}"
group="leads"
#end="handleChange"
data-id="4"
>
And access data-id attribute in handleChange function
handleChange(event){
console.log(event.from.getAttribute("data-id"))
console.log(event.to.getAttribute("data-id"))
}
`