VueJS how to make a button disabled, under different conditions? - vue.js

I have a button on my website that gives bonuses to the user. I need to make several conditions in 1 button.
If heal_used = 1 or diff < 1, the button must be disabled. I tried to do it like this:
<button v-if="heal_used 1" :disabled="diff < 1" v-else class="btn btn--small btn--purple" #click="takeBonus">Take</button>
But nothing worked. Also, if the button is active and the user can get a bonus, after the bonus you need to make the button inactive. I did it like this:
if (data.type === 'success') {
this.bonus_num = data.bonus_num;
this.heal_used = data.heal_used;
this.$forceUpdate();
}
Is it true? Can you help me please, to make 2 condifitions?
UPDATE
I change code to:
<button class="btn btn--small btn--purple" :disabled="isDisabled" #click="takeBonus">Take</button>
And add:
computed: {
isDisabled() {
return this.heal_used = 1 || this.diff < 10;
},
},
Console.log say me:
console.log(data.heal_used);
console.log(data.diff);
0
17
But button is stil; disabled, what's wrong?
UPDATE takeBonus:
takeBonus() {
this.$root.axios.post('/user/takeBonus', {
value: this.user.cashback
})
.then(res => {
const data = res.data;
if (data.type === 'success') {
this.bonus_num = data.bonus_num;
this.$root.user.balance = data.newBalance;
this.heal_used = data.heal_used;
this.$forceUpdate();
}
this.$root.showNotify(data.type, this.$t(`index.${data.message}`));
})
},

new Vue({
el: '#example',
data: {
heal_used : 4,
diff: 3
},
methods: {
takeBonus1: function () {
this.heal_used=1;
this.diff=0;
},
takeBonus2: function () {
this.heal_used=1;
this.diff=4;
},
takeBonus3: function () {
this.heal_used=2;
this.diff=.1;
},
reset: function () {
this.heal_used=4;
this.diff=3;
}
}
})
<head>
<title>My first Vue app</title>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.12"></script>
</head>
<body>
<div id="example">
<p>
<span>heal_used: {{ heal_used }}</span>
<span>diff: {{ diff }}</span>
</p>
<button
#click="takeBonus1()"
:disabled="heal_used===1 || diff < 1" >
Take bonus (both)
</button>
<br>
<button
#click="takeBonus2()"
:disabled="heal_used===1 || diff < 1" >
Take bonus (heal_used===1)
</button>
<br/>
<button
#click="takeBonus3()"
:disabled="heal_used===1 || diff < 1" >
Take bonus (diff < 1)
</button>
<br>
<button
#click="reset()">
Reset
</button>
</div>
</body>

Related

How to make increment/decrement cart count in vue

I've created a function for increment and decrement so that I can change the count in the cards.count.
The function for increment count works like this
but the functions for decrement count, it doesn't work.
When I click the function for decrement, this output will appear
Error in v-on handler: "TypeError: Cannot read property 'product_id' of undefined"
I don't know why there is an error in the product_id, even though the increment function also has a product_id.
I hope you can help me figured out the problem
<template>
<div v-if="cartList && cartList.length > 0">
<div
class="item-loop container col"
v-for="(cards, index) in cartList"
:key="generateKey(cards.product_id, cards.count)"
>
<div class="items row">
<div class="image col-4">
<img class="img-fluid pt-2" :src="cards.product_img" />
</div>
<div class="content text-left col-8">
<button
v-on:click="cartList.splice(index, 1)"
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">×</span>
</button>
<h5 class="text-left">{{ cards.product_name }}</h5>
<div class="prices" :key="cards.product_id">
<div class="value-cart form-group row">
<font-awesome-icon
:icon="['far', 'minus-square']"
size="2x"
class="minus-button"
#click="min(cards.product_id)"
/>
<input
type="number"
class="input-pm bg-light form-control p-0 text-center angka"
:value="cards.count"
/>
<font-awesome-icon
:icon="['far', 'plus-square']"
size="2x"
class="plus-button"
#click="plus(cards.product_id)"
/>
</div>
<p>Rp. {{ cards.product_price * cards.count }}</p>
</div>
</div>
</div>
</div>
<div class="cart-order">
<div class="order-total">
<div class="row">
<h4 class="col-6 font-weight-bold text-left">Total</h4>
<h5 class="col-6 font-weight-bold text-right">
Rp. {{ totalprice }}
</h5>
</div>
</div>
<p class="text-left"><strong>*Not including tax(10%)</strong></p>
<b-button
class="mt-3"
variant="primary"
#click="invoice()"
v-b-modal="'modal-checkout'"
block
>Checkout</b-button
>
<b-button class="mt-2" variant="danger" #click="resetcart" block>
Cancel </b-button
><br /><br />
</div>
</div>
</template>
export default {
components: {
Features,
Card,
},
data() {
return {
datamenu: {},
cartList: [],
invoiceid: 0,
tax: 0,
searchMenu: null,
menu: null,
formCheck: {
amount: 0,
invoice: "",
cashier: "abiwardani",
menu_name: "",
},
};
},
methods: {
plus(product_id) {
let result = this.cartList.find((res) => {
if (res.product_id == product_id) {
return res.product_id;
}
});
if (result) {
for (let i = 0; i < this.cartList.length; i++) {
if (this.cartList[i].product_id == product_id) {
const newFoodObject = {
...this.cartList[i],
count: this.cartList[i].count + 1,
};
console.log("plus");
this.$set(this.cartList, i, newFoodObject);
}
}
}
},
min(product_id) {
let result = this.cartList.find((res) => {
if (res.product_id == product_id) {
return res.product_id;
}
});
if (result) {
for (let i = this.cartList.length; i > 0; i--) {
if (this.cartList[i].product_id == product_id && this.cartList[i].count > 0){
const newFoodObject = {
...this.cartList[i],
count: this.cartList[i].count - 1,
};
this.$set(this.cartList, i, newFoodObject);
}
}
}
},
generateKey(key1, key2) {
return `${key1}-${key2}`;
},
},
mounted() {
axios
.get(process.env.VUE_APP_URL + "product")
.then((res) => {
this.datamenu = res.data.result;
})
.catch((err) => {
console.log(err);
});
}
Option 1:
i should start with length-1 and should go up to 0
min(product_id) {
let result = this.cartList.find((res) => {
if (res.product_id == product_id) {
return res.product_id;
}
});
if (result) {
for (let i = this.cartList.length-1; i >= 0; i--) {
if (this.cartList[i].product_id == product_id && this.cartList[i].count > 0){
const newFoodObject = {
...this.cartList[i],
count: this.cartList[i].count - 1,
};
this.$set(this.cartList, i, newFoodObject);
}
}
}
Option 2:
You do not need 2 methods.. just have one
updateQty(product_id,mode) {
let result = this.cartList.find((res) => {
if (res.product_id == product_id) {
return res.product_id;
}
});
if (result) {
for (let i = 0; i < this.cartList.length; i++) {
if (this.cartList[i].product_id == product_id) {
const newFoodObject = {
...this.cartList[i],
count: mode === 'INCRE' ? this.cartList[i].count + 1 : this.cartList[i].count - 1,
};
console.log("plus");
this.$set(this.cartList, i, newFoodObject);
}
}
}
},
use it like
<font-awesome-icon
:icon="['far', 'minus-square']"
size="2x"
class="minus-button"
#click="updateQty(cards.product_id,'INCRE')"
/>
and
<font-awesome-icon
:icon="['far', 'minus-square']"
size="2x"
class="minus-button"
#click="updateQty(cards.product_id,'DECRE')"
/>
Your problem is in the final expression of your for statement inside your min() method.
Change 'i--' with 'i++' to increase your index in each iteration. This will avoid accessing the 'cartList' array with a negative index (which is causing the problem, as it gets undefined):
min(product_id) {
let result = this.cartList.find((res) => {
if (res.product_id == product_id) {
return res.product_id
}
})
if (result) {
for (let i = this.cartList.length; i > 0; i++) {
👆
...
Here is how I did that
HTML:
<button #click="increment()">+</button>
<input :value="amount" />
<button #click="decrement()">-</button>
JS:
data() {
return {
amount: 0,
};
},
methods: {
increment() {
this.amount++;
},
decrement() {
this.amount--;
},
},

How to make disabled button after click in Vuejs

I have a button on my website that gives bonuses to the user. Button have several conditions in 1 button:
<button class="btn btn--small btn--purple" :disabled="isDisabled" #click="takeBonus">Take</button>
<script>
......
computed: {
isDisabled() {
return this.heal_used === 1 || this.diff < 10;
this.$forceUpdate();
},
},
.......
</script
But when user click Take button, and if all success, button is still active this.$forceUpdate(); not working. And i need make when user click Take button, and if all success, make this button disabled.
My full Bonus.vue:
<template>
<div class="inner-page">
<div class="account" v-if="loaded && !$root.isMobile">
<div class="page-header">
</div>
<div class="form-panels hide-below-m">
<div class="col-7" style="margin-top: 5rem;margin-right: 3rem;">
<div class="faucet-component mx-5" rv-class-boost="data.boostIsOpen">
<img src="https://dota2.skins1.games/src/img/components/shine.png?v=8ce59643e70cb2f8550deb6a249b5f29" class="faucet-component__shine-bg">
<div class="faucet-component__content d-flex justify-content-between align-items-center flex-column w-100" style="
height: 15rem;">
<div class="faucet-component__available-amount-block round-circle p-2">
<div class="faucet-component__availabe-amount-coins d-flex justify-content-center align-items-center round-circle h-100" rv-currency="model:amount">Спасение</div>
</div>
<!-- rivets: unless model:cnt | eq 0 --><div class="faucet-component__remaining">
<span rv-t="">Left</span>:
<span>{{ bonus_num }}</span><br>
<span rv-t=""></span>
<span>{{ diff }}</span>
</div>
<!-- rivets: if model:cnt | eq 0 -->
<div class="faucet-component__buttons-container d-flex align-items-center w-75 justify-content-around">
<button class="btn btn--small btn--purple" :disabled="isDisabled" #click="takeBonus">Take</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
loaded: false,
bonus: {},
diff: {},
user: {},
bonus_num: 0,
heal_used: {}
}
},
mounted() {
this.$root.isLoading = true;
if (!this.$cookie.get('token')) {
this.$root.isLoading = false;
this.$router.go(-1);
}
this.domain = window.location.protocol + '//' + window.location.hostname;
setTimeout(() => {
this.getUser();
}, 100);
},
computed: {
isDisabled() {
return this.heal_used === 1 || this.diff < 10;
this.$forceUpdate();
},
},
methods: {
getUser() {
this.$root.axios.post('/user/getProfile')
.then(res => {
const data = res.data;
console.log(data.heal_used);
console.log(data.diff);
this.loaded = true;
this.user = data.user;
this.bets = data.bets;
this.bonus = data.bonus;
this.diff = data.diff;
this.heal_used = data.heal_used;
this.new_day = data.new_day;
this.bonus_num = data.bonus_num;
this.$root.isLoading = false;
})
.catch(err => {
this.$root.isLoading = false;
this.$router.go(-1);
})
},
takeBonus() {
this.$root.axios.post('/user/takeBonus', {
value: this.user.cashback
})
.then(res => {
const data = res.data;
if (data.type === 'success') {
console.log(data.heal_used);
this.bonus_num = data.bonus_num;
this.$root.user.balance = data.newBalance;
this.heal_used = data.heal_used;
this.$forceUpdate();
}
this.$root.showNotify(data.type, this.$t(`index.${data.message}`));
})
},
}
}
How i can make it, when user click Take button, and if all success, so that the Take button becomes disabled?
I'm sorry but your code has no indentation, so I just did that on jsfiddler so you know "How to make disabled button after click in Vuejs". You can have a look on : https://jsfiddle.net/o81yvn05/1/
<div id="app">
<button :disabled="isDisabled" #click="disableButton()">Please click here</button>
</div>
<script>
new Vue({
el: "#app",
data: {
isDisabled: false,
},
methods: {
disableButton() {
this.isDisabled = true
}
}
})
</script>

State of variable not binding

<button id="btn1"> Button 1 </button>
<button id="btn2" v-if="state == 2"> Button 2 </button>
export default {
data() {
return {
emailPreferences: {
isLoading: false
},
state: 0
}
},
methods: {
OnBtn1Click() {
this.state = 2;
}
}
}
I'm trying to show the button "btn2" when I click the Button 1. But it doesn't seems to work.
Just putting #skirtle's comment in an awnser:
new Vue({
el: '#app',
data: {
state: 0
},
methods: {
OnBtn1Click() {
this.state = 2;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="OnBtn1Click" id="btn1"> Button 1 </button>
<button id="btn2" v-if="state == 2"> Button 2 </button>
</div>
The logic of your code was fine, just had the 'onclick' property missing for the button
Add a click event on the button
<button #click="OnBtn1Click" id="btn1"> Button 1 </button>

Multiple Stopwatch using VUe

I am a newbie to Vue.
I am working on multiple stopwatch using Vue.
I'm stuck, becuase my component is updating the values on all instances of the components, instead of just in one.
This is what I tried:
<div id="app">
<user-name></user-name>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.js"></script>
<script type='text/x-template' id="test-template">
<div>
<div class="column" v-for="(item, index) in items" :key="index">
<div class="ui segment">
<h3 class="ui blue header">{{parentTitle}}</h3>
<h2 class="ui greenheader">{{item.name}}</h2>
<div class="column">
<p class="ui huge header">
{{ hours }} :
{{ minutes | zeroPad }} :
{{ seconds | zeroPad }} :
{{ milliSeconds | zeroPad(3) }}</p>
<button class="ui secondary button" #click="startTimer"
:disabled="isRunning">START</button>
<button class="ui button" #click="pushTime" :disabled="!isRunning">LAP</button>
<button class="ui button" #click="stopTimer" :disabled="!isRunning">STOP</button>
<button class="ui basic button" #click="clearAll">CLEAR</button><br><br>
<ul class="ui bulleted list" v-if="times.length">
<li class="item" v-for="item in times">
{{ item.hours }} :
{{ item.minutes | zeroPad }} :
{{ item.seconds | zeroPad }} :
{{ item.milliSeconds | zeroPad(3) }}
</li>
</ul>
<br><br>
</div>
</div>
</div>
</div>
</script>
<script>
Vue.component('user-name', {
data() {
return {
parentTitle: "Employee Names",
test: "welcome",
times: [],
animateFrame: 0,
nowTime: 0,
diffTime: 0,
startTime: 0,
isRunning: false,
items: [{
id: 1,
name: 'Employee 1'
},
{
id: 2,
name: 'Employee 2'
}
],
count: 0
}
},
template: '#test-template',
methods: {
// 現在時刻から引数に渡した数値を startTime に代入
setSubtractStartTime: function (time) {
var time = typeof time !== 'undefined' ? time : 0;
this.startTime = Math.floor(performance.now() - time);
},
// タイマーをスタートさせる
startTimer: function () {
// loop()内で this の値が変更されるので退避
var vm = this;
//console.log(this);
//alert(timer0.innerText);
vm.setSubtractStartTime(vm.diffTime);
// ループ処理
(function loop() {
vm.nowTime = Math.floor(performance.now());
vm.diffTime = vm.nowTime - vm.startTime;
vm.animateFrame = requestAnimationFrame(loop);
}());
vm.isRunning = true;
//alert(innerText);
},
// タイマーを停止させる
stopTimer: function () {
this.isRunning = false;
cancelAnimationFrame(this.animateFrame);
},
// 計測中の時間を配列に追加
pushTime: function () {
this.times.push({
hours: this.hours,
minutes: this.minutes,
seconds: this.seconds,
milliSeconds: this.milliSeconds
});
},
// 初期化
clearAll: function () {
this.startTime = 0;
this.nowTime = 0;
this.diffTime = 0;
this.times = [];
this.stopTimer();
this.animateFrame = 0;
}
},
computed: {
// 時間を計算
hours: function () {
return Math.floor(this.diffTime / 1000 / 60 / 60);
},
// 分数を計算 (60分になったら0分に戻る)
minutes: function () {
return Math.floor(this.diffTime / 1000 / 60) % 60;
},
// 秒数を計算 (60秒になったら0秒に戻る)
seconds: function () {
return Math.floor(this.diffTime / 1000) % 60;
},
// ミリ数を計算 (1000ミリ秒になったら0ミリ秒に戻る)
milliSeconds: function () {
return Math.floor(this.diffTime % 1000);
}
},
filters: {
// ゼロ埋めフィルタ 引数に桁数を入力する
// ※ String.prototype.padStart() は IEじゃ使えない
zeroPad: function (value, num) {
var num = typeof num !== 'undefined' ? num : 2;
return value.toString().padStart(num, "0");
}
}
});
new Vue({
el: "#app",
});
</script>
Here is a working JSFiddle sample here
Any help highly appreciated.
Here is a solution to your problem jsfiddle
In your code you are mixing the data form your vue instance, with the data of your component.
Instead of having 1 component you can add your component multiple times with the v-for
This is your vue instance + data:
new Vue({
el: "#app",
data() {
return {
people: [{
id: 1,
name: 'Employee 1'
},
{
id: 2,
name: 'Employee 2'
}
]
}
}
});
The solution is to pass the data of the person to a component via props (here called item), and render this component as many time as needed in the array. This way, each component is a independent "instance".
<user-name v-for="(person, index) in people" :key="person.id" :item="person"></user-name>
Vue.component('user-name', {
props:['item'],
.....

Pagination. How to make moving between pages by clicking on numerals

Tell me how to make it so that when you click on a button from a cycle with page numbers, this particular page opens. Switching along the arrows works for me, but I cannot understand how to switch between pages. I take data from Api. Total posts 98. It is possible to add your posts. On one page only 10 posts are shown.
My html:
<div id="app">
<div class="smallfon">
<div class="blocktwitter"><img src="src/assets/twitter.png" class="twitter"/></div>
<div class="addTextPost">Add a post</div>
<input type="text" v-model="createTitle" class="created"/>
<input type="text" v-model="createBody" class="created"/>
<div><button #click="addPost()" class="addPost">AddPost</button></div>
<div class="post1">
<div class="yourPosts">Your Posts</div>
<ul>
<li v-for="(post, index) of paginatedData" class="post">
<p><span class="boldText">Title:</span> {{ post.title }}</p>
<p><span class="boldText">Content:</span> {{ post.body }}</p>
<button #click="deleteData(index, post.id)" class="buttonDelete">Delete</button>
<button #click="visiblePostID = post.id" class="buttonChange">Change</button>
<div v-if="visiblePostID === post.id" class="modalWindow">
<div><input v-model="post.title" class="changePost"><input v-model="post.body" class="changePost"></div>
<button type="button" #click="changePost(post.id, post.title, post.body)" class="apply">To apply</button>
</div>
</li>
</ul>
<button type="button" #click="page -=1" v-if="page > 0" class="prev"><<</button>
<button class="item"
v-for="n in evenPosts"
:key="n.id"
v-bind:class="{'selected': current === n.id}">{{ n }} </button>
<button type="button" #click="page +=1" class="next" v-if="page < evenPosts-1">>></button>
</div>
</div>
</div>
My js:
export default {
el: "#app",
data () {
return {
current: null,
page: 0,
posts: [],
createTitle: '',
createBody: '',
visiblePostID: '',
}
},
watch: {
counter: function(newValue, oldValue) {
this.getData()
}
},
created(){
this.getData()
},
computed: {
evenPosts: function(posts){
return Math.ceil(this.posts.length/10);
},
paginatedData() {
const start = this.page * 10;
const end = start + 10;
return this.posts.slice(start, end);
}
},
methods: {
setCurrent: function(id) {
this.current = id;
},
getData() {
axios.get(`https://jsonplaceholder.typicode.com/posts`).then(response => {
this.posts = response.data
})
},
deleteData(index, id) {
axios.delete('http://jsonplaceholder.typicode.com/posts/' + id)
.then(response => {
console.log('delete')
this.posts.splice(index, 1);
})
.catch(function(error) {
console.log(error)
})
},
addPost() {
axios.post('http://jsonplaceholder.typicode.com/posts/', {
title: this.createTitle,
body: this.createBody
}).then((response) => {
this.posts.unshift(response.data)
})
},
changePost(id, title, body) {
axios.put('http://jsonplaceholder.typicode.com/posts/' + id, {
title: title,
body: body
})
},
}
}
Screenshot of application
add click event #click="page=n" in button
<button #click="page=n" class="item"
v-for="n in evenPosts"
:key="n.id"
v-bind:class="{'selected': current === n.id}">{{ n }} </button>
Codepen : https://codepen.io/anon/pen/bZOROO