I try to add shopping cart,but I do not know how to do it. When count = 0,- is hidden.And when count > 0,- is show.When i try to click +, automatically increase 1, click - automatically reduced by 1. But can not be displayed.jsfiddle
Look at the Javascript file:
const goods = [{
id: "1",
goods_name: "水立方",
goods_price: "30.00",
goods_num: "15",
count:"0"
}, {
id: "2",
goods_name: "农夫山泉",
goods_price: "28.00",
goods_num: "10",
count:"0"
}]
var app = new Vue({
el: "#app",
data: {
list: goods,
},
methods: {
addCart(item,event) {
if (!this.item.count) {
Vue.set(this.item, 'count', 1);
} else {
this.item.count++;
}
},
lessCart(event) {
this.item.count--;
}
}
})
HTML file:
<div id="app">
<ul>
<li v-for="item in list">
<p>{{item.goods_name}}</p>
<p>{{item.goods_price}}</p>
<a v-show="item.count > 0" #click.stop.prevent="lessCart(item,$event)">-</a>
<input v-show="item.count > 0" v-model="item.count">
<a #click.stop.prevent="addCart(item,$event)">+</a>
</li>
</ul>
</div>
You are mutating the same state each time and not the state from the list.
You should simply do:
const goods = [{
id: "1",
goods_name: "水立方",
goods_price: "30.00",
goods_num: "15",
count:"0"
}, {
id: "2",
goods_name: "农夫山泉",
goods_price: "28.00",
goods_num: "10",
count:"0"
}]
var app = new Vue({
el: "#app",
data: {
list: goods,
},
methods: {
addCart(item) {
item.count++;
},
lessCart(item) {
item.count--;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in list">
<p>{{item.goods_name}}</p>
<p>{{item.goods_price}}</p>
<a v-show="item.count > 0" #click.stop.prevent="lessCart(item)">-</a>
<input v-show="item.count > 0" v-model="item.count">
<a #click.stop.prevent="addCart(item)">+</a>
</li>
</ul>
</div>
Note that you do not need the event argument in your method.
Related
Please can someone teach me the method to swap two different data on click
For example, we have a data
data() {
return {
data_one: [
{
name: "Simo",
age: "32"
}
],
data_two: [
{
name: "Lisa",
age: "25"
}
],
}
},
then I want to put this data on v-for, and I want to add two buttons to swap from data_one and data_two and display data_one as default.
<button #click="change_to_data_one">Data 1<button>
<button #click="change_to_data_two">Data 2<button>
<li v-for="item in data_one">{{item.name}} - {{item.age}}<li>
🙏🙏🙏🙏🙏
Try to use computed property:
new Vue({
el: "#demo",
data() {
return {
data_one: [{name: "Simo", age: "32"}],
data_two: [{name: "Lisa", age: "25"}],
selected: "data_one"
}
},
computed: {
showData(){
return this[this.selected]
}
},
methods: {
swap(val) {
this.selected = val
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<button #click="swap('data_one')">Data 1</button>
<button #click="swap('data_two')">Data 2</button>
<ul>
<li v-for="(item, i) in showData" :key="i">{{item.name}} - {{item.age}}</li>
</ul>
</div>
I am have an array of items that will be fetched fom an API. First, I display the string replacing ### with ______. Then when I click the buttons I want to replace them with <span>word</span>. so I'am using using v-html. I thought the new element would be shown but it doesn't. what would I have to do?
Code: https://jsfiddle.net/uosm30p9/
var example1 = new Vue({
el: '#example',
data: {
items: [{
str: 'This is ###.',
list: ['Frank', 'Eva']
},
{
str: 'I am not ###.',
list: ['George', 'John', 'Mark']
}
],
},
computed: {},
methods: {
createStr(item) {
item.newStr = item.str;
item.newStr = item.newStr.replace("###", "________")
return item.newStr
},
update(item, word) {
item.newStr = item.str;
var span = "<span class='.span1'>" + word + "</span>";
item.newStr = item.newStr.replace("###", span)
console.log(item.newStr);
}
}
});
.span1 {
color: blueviolet;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="example">
<ul>
<li v-for="(item,i) in items">
<span v-html="createStr(item)"></span>
<ul>
<li v-for="(word,j) in item.list">
<button v-on:click="update(item,word)">{{word}}</button>
</ul>
</li>
</ul>
</div>
Ok, in order to solve your problem more easily and separating concerns, I came to a solution by setting up a template and storing the current value in each element "state".
HTML:
<div id="example">
<ul>
<li v-for="(item,i) in items">
<span v-html="createStr(item)"></span>
<ul>
<li v-for="(word,j) in item.list">
<button v-on:click="update(item, j)">{{word}}</button>
</ul>
</li>
</ul>
</div>
Javascript:
var example1 = new Vue({
el: '#example',
data: {
defaultReplacement: "_________",
items: [{
selectedOption: null,
template: 'This is <b class="span1">###</b>.',
list: ['Frank', 'Eva']
},
{
selectedOption: null,
template: 'I am not <b class="span2">###</b>.',
list: ['George', 'John', 'Mark']
}
],
},
computed: {},
methods: {
createStr(item) {
var listItem = (item.selectedOption != null) ? item.list[item.selectedOption] : this.defaultReplacement;
return item.template.replace("###", listItem);
},
update(item, j) {
item.selectedOption = j;
}
}
});
Here's the working example: https://jsfiddle.net/feload/rhnf8zv4/5/
var example1 = new Vue({
el: '#example',
data: {
items: [{
str: 'This is ###.',
list: ['Frank', 'Eva'],
current: "________"
},
{
str: 'I am not ###.',
list: ['George', 'John', 'Mark'],
current: "________",
}
],
},
computed: {},
methods: {
createStr(item) {
item.newStr = item.str;
item.newStr = item.newStr.replace("###", item.current);
return item.newStr;
},
update(item, word, idx) {
item.current = word;
this.$set(this.items, idx, item);
}
}
});
.span1 {
color: blueviolet;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="example">
<ul>
<li v-for="(item,i) in items">
<span v-html="createStr(item)"></span>
<ul>
<li v-for="(word,j) in item.list">
<button v-on:click="update(item,word, i)">{{word}}</button>
</ul>
</li>
</ul>
</div>
First try making your data object reactive so that alterations to the item array can be observed by Vue:
data: function () {
return {
items: [
{
str: 'This is ###.',
list: ['Frank', 'Eva']
},
{
str: 'I am not ###.',
list: ['George', 'John', 'Mark']
}
]
}
},
Look at the example at the bottom of this page:
https://v2.vuejs.org/v2/guide/reactivity.html
Quick question. If I have data in an element in the form of an array as follow:
data: {
product: socks,
variants: [
{
variantId: 2234,
variantColor: 'Green',
variantQuantity: 0,
},
{
variantId: 2235,
variantColor: 'Blue',
variantQuantity: 10,
}
}
how can I select a certain variantQuantity based on me hovering over a certain div?
Full code:
HTML:
<div class="product-image">
<img :src="image" />
</div>
<div class="product-info">
<h1>{{ product }}</h1>
<p v-if="inStock">In Stock</p>
<p v-else :class="{ outOfStock: !inStock }">Out of Stock</p>
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
<div class="color-box"
v-for="variant in variants"
:key="variant.variantId"
:style="{ backgroundColor: variant.variantColor }"
#mouseover="updateProduct(variant.variantImage)"
>
</div>
<button v-on:click="addToCart"
:disabled="!inStock"
:class="{ disabledButton: !inStock }"
>
Add to cart
</button>
<div class="cart">
<p>Cart({{ cart }})</p>
</div>
</div>
Javascript:
var app = new Vue({
el: '#app',
data: {
product: 'Socks',
image: 'https://dl.dropboxusercontent.com/s/9zccs3f0pimj0wj/vmSocks-green-onWhite.jpg?dl=0',
inStock: false,
details: ['80% cotton', '20% polyester', 'Gender-neutral'],
variants: [
{
variantId: 2234,
variantColor: 'green',
variantImage: 'https://dl.dropboxusercontent.com/s/9zccs3f0pimj0wj/vmSocks-green-onWhite.jpg?dl=0',
variantQuantity: 0
},
{
variantId: 2235,
variantColor: 'blue',
variantImage: 'https://dl.dropboxusercontent.com/s/t32hpz32y7snfna/vmSocks-blue-onWhite.jpg?dl=0',
variantQuantity: 10
}
],
cart: 0
},
methods: {
addToCart() {
this.cart += 1
},
updateProduct(variantImage) {
this.image = variantImage
}
}
})
You could include variant.variantQuantity in the mouseover event-handler expression:
<div v-for="variant in variants"
#mouseover="updateProduct(variant.variantImage, variant.variantQuantity)"
>
Also add a data property for quantity, and update the handler to accommodate the new property:
data() {
return {
quantity: 0,
// ...
};
},
methods: {
updateProduct(variantImage, variantQuantity) {
this.image = variantImage;
this.quantity = variantQuantity;
},
// ...
}
demo based on your codepen
How can we highlight a item in a list of item when the particular item is clicked? Should we use id as reference?
<li v-for="todo in todos">
<label>
<a href="#"
v-on:click="toggle(todo)"
:style="{color:activeColor}"
>
{{ todo.text }}
</a>
</label>
</li>
toggle: function(todo){
this.activeColor = 'red'
}
I tried here:
https://jsfiddle.net/eywraw8t/110976/
You can add activeIndex to store current active index:
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="(todo, idx) in todos">
<label>
<a href="#"
v-on:click="toggle(idx)"
v-bind:checked="todo.done"
:class="{'active': idx == activeIndex}"
>
{{ todo.text }}
</a>
</label>
</li>
</ol>
</div>
new Vue({
el: "#app",
data: {
activeColor:String,
todos: [
{ text: "Learn JavaScript", done: false },
{ text: "Learn Vue", done: false },
{ text: "Play around in JSFiddle", done: false },
{ text: "Build something awesome", done: false }
],
activeIndex: null
},
methods: {
toggle: function(index){
this.activeIndex = index
}
}
and in css
.active {
color: red;
}
Demo: https://jsfiddle.net/Lv7eanru/
This is another solution to highlight selected item in a list using VueJS :
<div id="app">
<ul>
<li v-for="value in objectArray" v-on:click="highlight($event)" >
First name : {{ value.firstName }} -- Last name : {{ value.lastName }}
</li>
</ul>
and in JS file we have:
Vue.createApp({
data() {
return {
objectArray: [{
firstName: 'John',
lastName: 'Doe'
},
{
firstName: 'Amily',
lastName: 'Brown'
},
{
firstName: 'Jack',
lastName: 'London'
},
],
}
},
methods: {
highlight: function (event) {
for (var i = 0; i < event.target.parentElement.children.length; i++) {
event.target.parentElement.children[i].classList.remove('bg-warning');
}
event.target.classList.add('bg-warning');
}
},
}).mount('#app');
I have a problem with binding checkboxes using Vuex. On checkbox I use v-model with variable which has getter and setter to set or get value in store, the problem is that I get wrong data in store and I don't understand what cause the problem. Checkboxes bind to store property and this property must contain array of id's from checkboxes, but when I click checkbox more than one time it rewrite or remove store values. Can anyone help me to understand why does this happens? Link to jsFiddle.
The code
const store = new Vuex.Store({
state: {
checkboxes: {},
checked: {}
},
mutations: {
setCheckboxes(state, dataObj){
console.log(dataObj);
state.checkboxes = dataObj.data;
let firstElem = dataObj.data[Object.keys(dataObj.data)[0]];
state.checked[firstElem.parent_id] = [firstElem.id];
console.log(state.checked);
},
setTreeState(state, dataObj){
state.checked[dataObj.id] = dataObj.value;
console.log(state.checked);
}
}
});
Vue.component('checkboxTree', {
template: "#checkboxTree",
});
Vue.component('checkboxToggle', {
template: "#checkboxToggle",
data(){
return {
store
}
},
computed: {
value:{
get(){
return store.state.checked[this.checkbox.parent_id];
},
set(val){
store.commit({
type: 'setTreeState',
id: this.checkbox.parent_id,
value: val
});
},
},
},
props: ['checkbox']
});
const app = new Vue({
el: "#app",
store,
data: {
checkboxData: {
...
},
},
mounted(){
this.$store.commit({
type: 'setCheckboxes',
data: this.checkboxData
});
}
})
Template
<div id="app">
<checkbox-tree :checkboxData="checkboxData"></checkbox-tree>
</div>
<template id="checkboxTree">
<div>
<p>checkbox tree</p>
<form>
<ul>
<li v-for="checkbox in $store.state.checkboxes">
<checkbox-toggle :checkbox="checkbox"></checkbox-toggle>
</li>
</ul>
</form>
</div>
</template>
<template id="checkboxToggle">
<div>
<label>{{ checkbox.id }}</label>
<input type="checkbox"
:value="checkbox.id"
:id="'checkbox-' + checkbox.id"
:name="'checkbox-' + checkbox.id"
v-model="value"
>
</div>
</template>
Okay, assuming you want checked to contain ids of selected objects, I had to restructure your code significantly:
const removeFromArray = (array, value) => {
const newArray = [...array];
const index = newArray.indexOf(value);
if (index > -1) {
newArray.splice(index, 1);
return newArray;
}
return array;
}
const store = new Vuex.Store({
state: {
checkboxes: {},
checked: [],
},
mutations: {
addToChecked(state, id) {
state.checked.push(id);
},
removeFromChecked(state, id) {
const newArray = removeFromArray(state.checked, id);
state.checked = newArray;
},
setCheckboxes(state, data) {
state.checkboxes = data;
},
}
});
Vue.component('checkboxTree', {
template: "#checkboxTree",
computed: {
checkboxes() {
return this.$store.state.checkboxes;
},
},
});
Vue.component('checkboxToggle', {
template: "#checkboxToggle",
computed: {
value:{
get(){
return this.$store.state.checked.indexOf(this.checkbox.id) > -1;
},
set(val){
const mutation = val ? 'addToChecked' : 'removeFromChecked';
this.$store.commit(mutation, this.checkbox.id);
},
},
},
props: ['checkbox'],
});
const app = new Vue({
el: "#app",
store,
data: {
checkboxData: {
"5479": {
"id": 5479,
"title": "Место оказания услуг",
"type": "checkbox",
"dependencies": "",
"description": "",
"parent_id": 5478,
"npas": ""
},
"5480": {
"id": 5480,
"title": "Способы оказания услуг",
"type": "checkbox",
"dependencies": "",
"description": "",
"parent_id": 5478,
"npas": "50"
},
"5481": {
"id": 5481,
"title": "Объем и порядок содействия Заказчика в оказании услуг",
"type": "checkbox",
"dependencies": "",
"description": "",
"parent_id": 5478,
"npas": "54"
},
}
},
computed: {
stateRaw() {
return JSON.stringify(this.$store.state, null, 2);
},
},
mounted() {
this.$store.commit('setCheckboxes', this.checkboxData);
const firstElementKey = Object.keys(this.checkboxData)[0];
const firstElement = this.checkboxData[firstElementKey];
this.$store.commit('addToChecked', firstElement.id);
}
})
<script src="https://unpkg.com/vue"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<div id="app">
<checkbox-tree :checkboxData="checkboxData"></checkbox-tree>
<pre v-text="stateRaw"></pre>
</div>
<template id="checkboxTree">
<div>
<p>checkbox tree</p>
<form>
<ul>
<li v-for="checkbox in checkboxes">
<checkbox-toggle :checkbox="checkbox"></checkbox-toggle>
</li>
</ul>
</form>
</div>
</template>
<template id="checkboxToggle">
<div>
<label>{{ checkbox.id }}</label>
<input
type="checkbox"
:value="checkbox.id"
:id="'checkbox-' + checkbox.id"
:name="'checkbox-' + checkbox.id"
v-model="value">
{{value}}
</div>
</template>
Using this code as an example, you can populate checked however you want to.
Also, a jsfiddle link for you: https://jsfiddle.net/oniondomes/ckj7mgny/