Vue JS - How to cancel active class on button click - javascript

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.

Related

How to filter checkbox by query api in vuejs?

I'm making a website that has a filter function before pouring data out... Currently, I'm doing the pretty stupid way of dumping all the data out and putting it in an object and then filtering. I want when I click on it, it will call the api to return according to the params that I pass, but the initial default is that the checkbox is in the all box, it still returns all. Here is my code part....
Template:
<template>
<div class="job">
<div class="container recruit flex-wrap">
<div class="job-filter">
<h3>
Ngành nghề
<img
id="icon-filter"
#click="showfilter"
:style="{ display: display.btn_show_filter }"
src="../assets/recruit/angle-down-svgrepo-com.svg"
alt=""
/>
<img
id="icon-close-filter"
:style="{ display: display.btn_close_filter }"
#click="closefilter"
src="../assets/recruit/close-svgrepo-com.svg"
alt=""
/>
</h3>
//Handle Filter
<div
class="radio-group"
id="group-filter"
:style="{ display: display.group_filter }"
>
<div
class="radio-check"
v-for="(check, index) in checks"
#click="selectFilter(check)"
:key="index"
>
<input
type="radio"
:id="index"
name="fav_language"
:value="check"
v-model="selected"
/>
<label :for="check">{{ check }}</label
><br />
</div>
</div>
</div>
//End Handle filter
<div class="search">
<div class="search-top flex-wrap">
<h5>{{ totalJobs }} {{ localised("countRecruit") }}</h5>
<div class="search-input">
<input
type="search"
placeholder="Nhập tên vị trí công việc"
v-model="search"
/>
<button #click="searchJob">
<img src="../assets/recruit/search.svg" alt="" />
</button>
</div>
</div>
<div
id="jobs"
class="job-item"
v-for="(item, index) in jobs"
:key="index"
:per-page="perPage"
:current-page="currentPage"
>
<router-link
tag="a"
:to="{ name: 'Detail', params: { id: item.id } }"
>
<h3 class="mleft-27">{{ item.Name }}</h3>
</router-link>
<div class="job-info flex-wrap">
<div class="job-info-left pleft-27 flex-wrap">
<div>
<img src="../assets/recruit/years.svg" alt="" />
<b>{{ item.Exprerience }}</b>
</div>
<div>
<img src="../assets/recruit/luong.svg" alt="" />
<b>{{ item.Salary }}</b>
</div>
<div>
<img src="../assets/recruit/diadiem.svg" alt="" />
<b>{{ item.Headequarters }}</b>
</div>
</div>
<div>
<h6>{{ momentTime(item.updatedAt) }}</h6>
</div>
</div>
<div class="info-job flex-wrap">
<div class="list-info-job">
<li>{{ item.Content }}</li>
</div>
<router-link
tag="a"
:to="{ name: 'Detail', params: { id: item.id } }"
>
<button class="btn-detail">Xem chi tiết</button>
</router-link>
</div>
</div>
<h3 class="not-found" v-show="showNoData">Not Found</h3>
</div>
</div>
</div>
</template>
And here is the js logic I'm dealing with:
<script>
import "../assets/style.css";
import "../assets/job.css";
import job from "../locales/lang";
import request from "#/utils/request";
import moment from "moment";
export default {
name: "jobs",
components: {},
data() {
return {
totalJobs: null,
tickTime: "",
currentPage: 1,
showPag: true,
showNoData: false,
perPage: 4,
search: "",
page: "",
noData: [],
checks: [
"All",
"Developer",
"Tester",
"Designer",
"Support",
"Marketing",
"Other",
],
jobinfos: [],
showJobs: [],
selected: "All",
};
},
computed: {
},
watch: {
// selected(newVal) {
// if (newVal === "All") {
// return this.jobinfos;
// } else {
// return this.jobinfos.filter((i) => i.Genres === newVal);
// }
// },
},
async mounted() {
//API
this.getJobs();
// event enter
var self = this;
window.addEventListener("keyup", function (event) {
if (event.keyCode === 13) {
self.searchJob();
}
});
},
methods: {
//Call api job information by locale
async getJobs() {
await request
.get(`jobs?_locale=${this.$route.params.locale}`)
.then((response) => {
this.jobinfos = response.data;
this.showJobs = response.data;
this.totalJobs = response.data.length;
})
.catch((e) => {});
},
//Filter item jobs
selectFilter(item) {
this.selected = item;
if (this.selected == "All") {
this.showJobs = this.jobinfos;
} else {
this.showJobs = this.jobinfos.filter((i) => i.Genres === this.selected);
if (this.showJobs.length > 0) {
this.showPag = true;
this.showNoData = false;
} else {
this.showPag = false;
this.showNoData = true;
}
}
},
// method search by filter
},
};
</script>
As for the backend, I'm using 3rd party cms, it probably already provides enough query params for me, please give me some pseudocode or a way so that when I click on the checkbox, it will call the api to return the records according to the check box ^^ thanks

How to make a clone of the array object with new id and same name?

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)
}
}

Adding item to cart and removing from cart

I have a + button to add item to cart,it works. But at the same time when number increments in cart I need number that says in stock will decrement number in stock that displays it doesn't work …
I need to do the same with - button
I really need the displayed inStock number to change when I add or remove items from cart
Can someone please help me? I'm new at this
Vue.component('product', {
template:
`
<div class="product">
<div class="product-image">
<img :src="image" />
</div>
<div class="product-info">
<h1>{{ product }}</h1>
<p v-if="inStock">In Stock {{inStock}}</p>
<p v-else>Out of Stock</p>
<button #click="addToCart"
:disabled="!inStock"
:class="{ disabledButton: !inStock }"> + </button>
<button #click="removeFromCart"> - </button>
</div>
</div>
`,
data() {
return {
product: 'Hoodie',
image: 'hoodie.jpeg',
inStock: 10,
cart: 0
}
},
methods: {
addToCart: function() {
this.$emit('add-to-cart')
},
removeFromCart: function() {
this.$emit('remove-from-cart')
}
}
})
var app = new Vue({
el: '#app',
data: {
cart: 0,
inStock: 10
},
methods: {
updateCart() {
this.cart += 1,
this.inStock -= 1,
},
removeItem() {
this.cart -= 1,
this.inStock += 1
}
}
})
HTML:
<div class="nav-bar"></div>
<div id="app">
<div class="cart">
<p>Cart({{ cart }})</p>
</div>
<product #add-to-cart="updateCart" #remove-from-cart="removeItem"></product>
</div>
Inside your component, remove the data attributes inStock and cart and props section.
Vue.component('product', {
template:
`
<div class="product">
<div class="product-image">
<img :src="image" />
</div>
<div class="product-info">
<h1>{{ product }}</h1>
<p v-if="inStock">In Stock {{inStock}}</p>
<p v-else>Out of Stock</p>
<button #click="addToCart"
:disabled="!inStock"
:class="{ disabledButton: !inStock }"> + </button>
<button #click="removeFromCart"> - </button>
</div>
</div>
`,
data() {
return {
product: 'Hoodie',
image: 'hoodie.jpeg',
}
},
props: {
inStock: {
type: Number,
default: 0
},
cart : {
type: Number,
default: 0
}
},
methods: {
addToCart: function() {
this.$emit('add-to-cart')
},
removeFromCart: function() {
this.$emit('remove-from-cart')
}
}
})
var app = new Vue({
el: '#app',
data: {
cart: 0,
inStock: 10
},
methods: {
updateCart() {
this.cart += 1,
this.inStock -= 1,
},
removeItem() {
this.cart -= 1,
this.inStock += 1
}
}
})
Then in your parent component, pass the props.
Parent Component (HTML)
<div class="nav-bar"></div>
<div id="app">
<div class="cart">
<p>Cart({{ cart }})</p>
</div>
<!-- changes for props added below -->
<product :cart="cart" :inStock="inStock" #add-to-cart="updateCart" #remove-from-cart="removeItem"></product>
</div>

Vue JS - How to bind two event #mouseover and #click at the same time

I have four pictures, when I hover the mouse over them, a certain component is displayed from below, but I still need to bind the click event, that is, when I click on the picture, the component should be displayed; when the component is clicked again, the problem is that I cannot bind two events at once at the same time
I understand that when the user hovers over the component, it will be immediately displayed and the click event will be useless, but I will need it in the mobile version
You can also look at my code in codesandbox
<template>
<div>
<div class="enjoy_headline_container">
<div class="EnjoyGirlsContainer">
<div>
<h3 style="margin: 0"></h3>
</div>
<div class="EnjoyGirlsList">
<div
v-for="(chunk, index) in Math.ceil(EnjoyGirlsList.length / 2)"
:key="'chunk-' + index"
:class="'wrap-' + index"
>
<div
v-for="(item, index) in EnjoyGirlsList.slice(
(chunk - 1) * 2,
chunk * 2
)"
:key="'img-' + index"
class="EnjoyCard"
:class="'EnjoyCard-' + index"
>
<div v-on:click="isHidden = !isHidden">
<img
#mouseover="mouseOver(item, (hover = true))"
:src="item.imagePath"
alt="Snow"
/>
</div>
<div class="EnjoyCardContainer">
<div
:style="{ background: item.textColor }"
class="EnjoyCardChildContainer"
>
<h3 class="EnjoyCardChildContainerTitleName">
{{ item.titleName }}
</h3>
</div>
</div>
<div
v-if="selected === item && !isHidden"
class="below-all-description EnjoyGirlsHoverEffect"
>
<div class="next-to-description EnjoyGirlsHoverEffect">
<div
style="width: 100%; display: flex; justify-content: center"
v-for="(enjoy, index) in EnjoyGirlsList"
:key="index"
>
<div
#mouseleave="mouseout(enjoy, (hover = false))"
class="EnjoyGirlsChildHoverEffect"
>
<component
v-show="enjoy.hovered"
v-bind:is="enjoy.componentName"
></component>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-if="!isHidden" class="below-all-description">
<template v-if="selected === null"></template>
<template v-else>
<div
style="width: 100%; display: flex; justify-content: center"
v-for="(enjoy, index) in EnjoyGirlsList"
:key="index"
>
<div
#mouseleave="mouseout(enjoy, (hover = false))"
class="EnjoyGirlsChildHoverEffect"
>
<component
v-show="enjoy.hovered"
v-bind:is="enjoy.componentName"
></component>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
</template>
<script>
import EnjoyBlue from "./components/EnjoyBlue";
import EnjoyGreen from "./components/EnjoyGreen";
import EnjoyYellow from "./components/EnjoyYellow";
import EnjoyRed from "./components/EnjoyRed";
export default {
name: "HomePage",
components: {
EnjoyRed,
EnjoyYellow,
EnjoyGreen,
EnjoyBlue,
},
data() {
return {
isHidden: false,
selected: null,
hover: false,
sectionGirlsListComponentsNames: [
"EnjoyRed",
"EnjoyYellow",
"EnjoyGreen",
"EnjoyBlue",
],
EnjoyGirlsList: [
{
imagePath: "https://i.ibb.co/mCpNXhG/IMG-6061-min.png",
titleName: "TEENS",
textColor: "#74C8C5",
hovered: false,
componentName: "EnjoyBlue",
},
{
imagePath: "https://i.ibb.co/WvJjwsN/Rectangle-2.png",
titleName: "MINXES",
textColor: "#76ED00",
hovered: false,
componentName: "EnjoyGreen",
},
{
imagePath: "https://i.ibb.co/7khc5f0/Rectangle-3.png",
titleName: "MILFS",
textColor: "#FFE600",
hovered: false,
componentName: "EnjoyYellow",
},
{
imagePath: "https://i.ibb.co/6nz97Bw/Rectangle-4.png",
titleName: "COURGARS",
textColor: "#CC003D",
hovered: false,
componentName: "EnjoyRed",
},
],
};
},
methods: {
mouseOver: function (enjoy) {
this.EnjoyGirlsList.forEach((enjoy) => (enjoy.hovered = false));
this.selected = enjoy;
enjoy.hovered = true;
if (this.hover) {
console.log("4949494");
}
},
mouseout: function (enjoy) {
this.selected = null;
enjoy.hovered = false;
},
mouseEnter: function () {},
Prev() {
this.$refs.carousel.prev();
},
showNext() {
this.$refs.carousel.next();
},
},
};
</script>
And so if you looked at this code in codesandbox (I left the link at the top), then you might have noticed that hover only works the first time after that it does not work, only the click event works
Your click event toggles isHidden. When you click on it you set isHidden to true. After that it won't show, if you hover over it since you are hiding it with v-if:
<div v-if="!isHidden" class="below-all-description">
...
</div>
Solution:
In your mouseOver function you explicitly have to set isHidden to false.
methods: {
mouseOver: function (enjoy) {
this.isHidden = false;
this.EnjoyGirlsList.forEach((enjoy) => (enjoy.hovered = false));
...
}
...
}

VueDraggable send request to DB while drag and drop

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"))
}
`

Categories

Resources