In Vue.js, is this a wrong writing for v-on? - javascript

i want to make two button to input number.
but when the left one goes to 10, it looks like this:
enter image description here
i want it to be 2 on the left while 0 on the right side.
so i changed my code:
<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal2"></button-counter>
<button-counter v-on:increment2="incrementTotal"></button-counter>
</div>
Vue.component('button-counter', {
template: '<button v-on:click="increment">{{ counter }}</button><button v-on:click="increment2">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
},
methods: {
increment: function () {
this.counter += 1
this.$emit('increment')
},
increment2:function () {
if(this.counter === 10){
this.counter = 0;
this.increment();
}
this.$emit('increment2')
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
},
incrementTotal2: function () {
this.total = this.total +10
}
}
})
but it did'nt work..enter image description here
i click the right button, the total number wont change.

You render 2 components each of them should render 2 buttons. Sounds about right? If you check Element Inspector you will see that rendered only 2 buttons. 2 + 2 === 2 - something is fishy...
Dev version of Vue telling you in console "Error compiling template... Component template should contain exactly one root element".
So each button-counter render first button => writing you warning => and ignoring second button.
<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter-1 #increment="incrementTotal"></button-counter-1>
<button-counter-2 #increment="incrementTotal"></button-counter-2>
</div>
Vue.component('button-counter-1', {
template: '<button #click="increment1">{{ counter }}</button>',
data: function() {
return { counter: 0 }
},
methods: {
increment1: function () {
this.counter++;
this.$emit('increment', 10);
}
}
});
Vue.component('button-counter-2', {
template: '<button #click="increment2">{{ counter }}</button>',
data: function() {
return { counter: 0 }
},
methods: {
increment2: function () {
this.counter++;
this.$emit('increment', 1);
}
}
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function (n) {
this.total += n;
},
}
})

Related

Having value loop from 100 to 0 - Vuejs

I'm trying to have my power value go from 100 to 0 and back from 0 to 100. This will be for a power meter where the user will hit a button to stop it at a random value.
Just need help getting the loop working properly
export default {
data() {
return {
power: 100,
};
},
}
watch:{
power: {
handler(value) {
if (value == 100 || value > 0) {
setTimeout(() => {
this.power--;
}, 100);
} if (value == 0) {
setTimeout(() => {
this.power++;
}, 100);
}
},
immediate: true
},
}
Maybe you could find other solutions also, but this is what comes in my mind:
<template>
<section v-if="!showPart">
<!-- This part is shown when program is cycling looping numbers -->
<div v-if="power1">
{{power}}
</div>
<div v-else>
{{powerReverse}}
</div>
</section>
<div v-else>
<!-- This part is shown when user clicks to select a number -->
{{showValue}}
</div>
<button #click="stopFunc">{{textBtn}}</button>
</template>
<script>
export default {
name: "powerCompo",
data() {
return {
speed: 100, // speed of loop
power: 99, // start point of loop
power1: true, // for change view in increase and decrease states
powerReverse: 0, // for increasing loop after reach to "0"
showValue: "nothing selected", // showing the selected value
decrease: null, // for clearing "timeout" in decrease mode
increase: null, // for clearing "timeout" in increase mode
showPart: false, // for changing view between "loop" or "stop" modes
textBtn: "click for stop" // defines the text of btn
};
},
watch:{
power: {
handler(value) {
this.decrease = setTimeout(() => {
this.power--;
}, this.speed);
if (this.power === 0) {
clearTimeout(this.decrease);
console.log("decrease");
this.power1 = false;
this.powerReverse = 0;
this.powerReverse++;
}
},
immediate: true
},
powerReverse(newValue) {
this.increase = setTimeout(() => {
this.powerReverse++;
}, this.speed);
if (this.powerReverse === 100) {
clearTimeout(this.increase);
console.log("increase");
this.power1 = true;
this.power = 100;
this.power--;
}
}
},
methods: {
stopFunc: function ($event) {
/* This function is called each time the user clicks on button. Then if the text of button is "click for cycling again", it calls "resetFunc()" method and if not, it stops looping and shows the selected value. */
if ($event.target.innerText === "click for cycling again") {
this.resetFunc();
} else {
if (this.power1) {
this.showValue = this.power;
if (this.showValue === 100) {
this.showValue = 99;
this.power = 99;
}
} else {
this.showValue = this.powerReverse;
}
this.showPart = true;
clearTimeout(this.increase);
clearTimeout(this.decrease);
this.textBtn = "click for cycling again"
}
},
resetFunc: function () {
clearTimeout(this.increase);
clearTimeout(this.decrease);
this.textBtn = "click for stop"
this.showPart = false;
this.power= 100;
this.power1= true;
}
}
}
</script>
With the above component you can loop between [1, 99] inclusive.

Watch a select quantity selector with Vue 3

I'm trying to make a quick shopping cart with on existing project.
My list items is already is generated by php and I get work with html elements like that :
const billets = document.querySelectorAll(".card-billet");
var products = [];
billets.forEach(billet => {
products.push({
title: billet.querySelector('.card-billet-title').textContent,
price: billet.dataset.price,
qty: billet.querySelector('select[name="billet_quantity"]').value
});
});
const App = {
data() {
return {
items: products
}
},
watch: {
items: function () {
console.log("watched");
},
},
computed: {
total: function () {
console.log(this.items)
let total = 0.00;
this.items.forEach(item => {
total += (item.price * item.qty);
});
return total;
}
}
}
Vue.createApp(App).mount('#checkoutApp')
This works but only on page load but I'm trying to change the total when my select quantity changeno.
I'm a bit lost to achieve this, should I use watch but on what ? Or anything else ?
Finally I found how to achieve this, the problem was that my array was out of the vue instance so can't be updated.
I simplified the code like this :
const App = {
data() {
return {
items: []
}
},
methods: {
onChange: function (e) {
// console.log(this.items)
this.items = [];
document.querySelectorAll(".card-billet").forEach(billet => {
this.items.push({
title: billet.querySelector('.card-billet-title').textContent,
price: billet.dataset.price,
qty: billet.querySelector('.card-billet-qty-selector').value
});
});
}
},
computed: {
total: function () {
// console.log(this.items)
let total = 0.00;
this.items.forEach(item => {
total += (item.price * item.qty);
});
return total;
}
}
}
Vue.createApp(App).mount('#checkoutApp')

clear interval on another function vue js

I'm confused how to add a set Interval variable in my vue file myTimer = setInterval(function, time).
The goal of my program is to change the number variable every 3 seconds, to access the object that I created to let it display different background images but I also have 2 buttons that can navigate through the background as well.
This is my template code
<div class="background" :style="{backgroundImage: `url(${Images[`${number}`].picture})`}">
<div class="content_container">
<div v-on:click="prev" class="prevButton"><p><</p></div>
<div class="title_container">
<div class="theTitle"><p>{{Images[`${number}`].Title}}</p></div>
</div>
<div v-on:click="next" class="nextButton"><p>></p></div>
</div>
</div>
This is my set Interval code
export default {
data: () => ({
number: 0,
myTimer
}),
mounted:function() {
this.$nextTick(() => {
this.timer();
});
},
methods:{
timer: function() {
var myTimer = setInterval(this.counter, 3000);
},
counter:function(){
if(this.number >= (this.Images.length -1)){
this.number = 0;
}
else{
this.number +=1;
}
},
next()
{
clearInterval(this.myTimer)
if(this.number >= (this.Images.length -1)){
this.number = 0;
}
else{
this.number +=1;
}
},
I want to clearInterval at the next() function how can I access the variable from another function.
your myTimer need be in this context.
export default {
data: () => ({
number: 0,
myTimer: 0, // init myTimer
}),
mounted: function () {
this.$nextTick(() => {
this.timer();
});
},
methods: {
timer: function () {
this.myTimer = setInterval(this.counter, 3000); // in this.myTimer
},
counter: function () {
if (this.number >= this.Images.length - 1) {
this.number = 0;
} else {
this.number += 1;
}
},
next() {
clearInterval(this.myTimer); // clear
if (this.number >= this.Images.length - 1) {
this.number = 0;
} else {
this.number += 1;
}
this.timer(); // start next
},
},
};

Bind Vue component to vue instance

I have Vue component here
Vue.component('number-input', {
props: {},
template: `<textarea class="handsontableInput subtxt area-custom text-center text-bold" v-model="displayValue" #blur="isInputActive = false" #focus="isInputActive = true"></textarea>`,
data: function() {
return {
isInputActive: false
}
},
computed: {
displayValue: {
get: function() {
if (this.isInputActive) {
return this.value.toString()
} else {
return this.value.toFixed(0).replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g, "$1,")
}
},
set: function(modifiedValue) {
let newValue = parseFloat(modifiedValue.replace(/[^\d\.]/g, ""))
if (isNaN(newValue)) {
newValue = 0
}
this.$emit('input', newValue)
}
}
}
})
and have methods change on vue instance as bellow
var content_kalkulasi = new Vue({
el: '#kalkulasi-table',
data: {
arr: [{id:'',name:'',file:'',satuan: 0,sub: 0}],
total: 0,
index_upload: 0
},
methods:{
add(){
arr = {}
arr.id = ''
arr.name = ''
arr.file = ''
arr.satuan = 0
arr.sub = 0
this.arr.push(arr)
},
change(){
this.total = 0
for(x in this.arr){
this.total += this.arr[x].satuan * this.arr[x].sub
}
console.log(this.total)
},
And I want to trigger method change from this html
<number-input style="" v-model="data.sub" v-on:keyup="change"></number-input>
butv-on:keyup="change" wont triggering. How i can call method v-on:keyup="change" from vue component? thank you
It is because your component isn't firing the keyup event.
Change v-on:keyup="change" to v-on:input="change"
Or in your component add this to the textarea :
#keyup="$emit('keyup')"

Change class for a VueJS component

I want to change the class of a component in VueJS after 2.5 seconds and I'm using this code:
const Header = {
template: `<header :class=hclass v-html="header"></header>`,
data () {
return {
hclass: 'off'
}
},
methods: {
changeVisibility () {
window.setTimeout(function () {
this.hclass = 'on'
console.log('Change to on!', this.hclass)
}, 2500)
}
},
computed: {
header () {
this.changeVisibility()
return store.state.header
}
}
}
While I see it in the console it says 'Change to on!', it never actually updates my class with 'on'!
Thank you for pointing to the right direction!
methods: {
changeVisibility () {
setTimeout(function () {
this.hclass = true
console.log('Change to on!', this.hclass)
}.bind(this), 5000)
}
}

Categories