Conditional operator less than is not working in Vuejs - vuejs2

i have an issue with less than operator in vuejs.
what i want is:
if original price is 10 and discount price 200, then the result (discount_price) should not be displayed,
else show the discount_price
The code doesn't seem to work. Here is the code:
HTML:
<div v-if="original_price > discount_price">
<span class="price-info mr-2">
{{ original_price | numeral('0,0') }}
</span>
<span>
{{ Number((original_price - discount_price) / original_price) * 100 + '%' }}
</span>
</div>
Please assist

Your v-if condition is not in the appropriate tag. It should be in the span of discount. Working demo below:
new Vue({
el: '#app',
data() {
return {
original_price: 10,
discount_price: 20
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'>
<span class="price-info mr-2">
{{ original_price | numeral('0,0') }}
</span>
<span v-if="original_price > discount_price">
{{ Number((original_price - discount_price) / original_price) * 100 + '%' }}
</span>
</div>

Related

Creating pagination component

I am trying to create pagination component. For e.g if my API returns "pages": 9
For example, if I have 9 pages, I want to cut the list at 5 and add three dots like on the image. I want to be able to provide at which index I can cut the list. Whats the best way to do this? I am approaching this wrong?
<div v-for="index in pages" class="flex">
<button>{{index}}</button>
</div>
Assuming you receive cutIndex and apiPages as props to your component, then your template could look something like the following:
<div v-for="page in Math.min(cutIndex, apiPages)" class="flex">
<button>{{page}}</button>
</div>
<template v-if="cutIndex < apiPages">
<div class="flex">
<button>...</button>
</div>
<div class="flex">
<button>{{apiPages}}</button>
</div>
</template>
this code works for me, and here is the key part
<template>
...
<template v-for="index in pages"
v-if="(index < 4 || (length - index) < 3) || Math.abs(index - value) < 2">
<span v-if="index === (length - 2) && value < (length - 4)">
...
</span>
<button #click.prevent="updatePage(index)">
{{ index }}
</button>
<span v-if="(index === 3 && value > 5)">
...
</span>
</template>
...
</template>
the result:
<template>
<nav class="flex items-center justify-center" role="pagination">
<!-- go to previous page -->
<a :key="`${$route.name}-arrow-${value > 1 ? value - 1 : 1}`"
:href="getFullPath(value > 1 ? value - 1 : 1)"
:title="$t('previous_page')"
#click.prevent="updatePage(value > 1 ? value - 1 : 1)"
:disabled="value === 1"
class="arrow pop-btn default rounded-sm"
v-waves>
<i class="mdi-chevron-left mdi"></i>
</a>
<template v-for="index in length"
v-if="(index < 4 || (length - index) < 3) || Math.abs(index - value) < 2">
<span v-if="index === (length - 2) && value < (length - 4)">
...
</span>
<a :href="getFullPath(index)"
:title="$t('page_index', {index: index})"
#click.prevent="updatePage(index)"
class="pop-btn number default rounded-sm"
:class="{
'active': index === value
}"
v-waves>
{{ index }}
</a>
<span v-if="(index === 3 && value > 5)">
...
</span>
</template>
<!-- go to next page -->
<a :href="getFullPath(value === length ? value : value + 1)"
:title="$t('next_page')"
#click.prevent="updatePage(value === length ? value : value + 1)"
:disabled="value === length"
class="arrow pop-btn default rounded-sm"
v-waves>
<i class="mdi-chevron-right mdi"></i>
</a>
</nav>
</template>
<script type="text/javascript">
export default{
emits: ['update:value],
props: {
length: {
required: true,
type: Number
},
// the page filter
value: {
required: true,
type: Number
}
},
methods: {
updatePage(index){
this.$emit('update:value', index);
},
getFullPath(page){
let query = {...this.$route.query};
page === 1 ? delete query.page : query.page = page;
return this.$router.resolve(
this.r({
query: query,
name: this.$route.name,
params: this.$route.params
})
).href;
}
}
}
</script>
by the way, <a> may better than <button> for SEO

foundation grid not working in vue js template

Am trying to loop through a list and display them in a grid with four cards.
<div class="grid-x movies">
<div v-for="item in filteredMovie" :key="item.id">
<div class="cell large-4 medium-3 small-12">
<div class="card">
<img v-bind:src="item.cover_image" style="height:100px;width: 100px">
{{ item.name }}<br/>
</div>
</div>
my computed property is
computed:{
items(){
return this.$store.getters.getMovies
},
filteredMovie:function(){
let self= this;
return this.items.filter(function(item){
return item.name.toLowerCase().indexOf(self.search.toLowerCase()) >= 0
|| item.cast.toLowerCase().indexOf(self.search.toLowerCase()) >= 0
|| item.genre.toLowerCase().indexOf(self.search.toLowerCase()) >= 0;
}
)
}
}
}
</div>
but the list doesn't display on the page but when i put the v-for before the grid the list shows but the cards are not in four columns.what could be the problem
You need to put your classes on the looping div:
<div class="cell large-4 medium-3 small-12" v-for="item in filteredMovie" :key="item.id">
Your code in a sample: https://jsfiddle.net/5b6zkLom/

Error setting default accordion item in class condition

In my laravel 5.7 / Vuejs ( vue": "^2.6.10" ) / "bootstrap": "^4.3.1" application
using accordion I want in debugging purpose show 1 block openec with template like:
<div :id="'collapse'+nextStateWithRegion.id" v-bind:class="'collapse'+{ ' show' : nextStateWithRegion.id == debugging_state_id }" :aria-labelledby="'heading'+nextStateWithRegion.id"
data-parent="#accordion_hostels_by_location">
<div class="card-body">
<!--{{ nextStateWithRegion.regionsOfStateArray }}-->
<ul>
<li v-for="nextRegionOfState, index in nextStateWithRegion.regionsOfStateArray" :key="nextRegionOfState.id">
<!--nextRegionOfState::{{ nextRegionOfState }}-->
<router-link :to="{ name: 'hostelsByRegion', params: { region_id: nextRegionOfState.id, state_id : nextRegionOfState.state_id } }"
class="nav-link">{{ nextRegionOfState.name }}
<small>( {{ nextRegionOfState.related_common_hostels_count }} hostels with {{ nextRegionOfState.related_featured_hostels_count }}
featured)</small>
</router-link>
</li>
</ul>
</div>
</div>
but result is different, as I see not ‘ show’ string added to the class, but ‘[object Object]’ :
https://imgur.com/a/YWenuxh
Which way is correct ?
Thanks!

Printing key in Vue.js iteration

I have array like below
data() {
return {
shoppingItems: [
{name: 'apple', price: '10'},
{name: 'orange', price: '12'}
]
}
}
I am trying to iterate like below
<ul>
<li v-for="item in shoppingItems">
{{ item.name }} - {{ item.price }}
</li>
</ul>
I am getting output like below
apple - 10
orange - 12
But I would like to get output like below
name - apple, price - 10 //I would like to print key dynamically
name - orange, price - 12
You can use (key,value) pair in for loop
var app = new Vue({
el:'#app',
data() {
return {
shoppingItems: [
{name: 'apple', price: '10'},
{name: 'orange', price: '12'}
]
}
}
});
li span{
text-transform: capitalize;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in shoppingItems">
<span v-for="(v,i,count) in item">{{i}} - {{v}}<span v-show="count<(Object.keys(item).length-1)
">, </span></span>
</li>
</ul>
</div>
You can iterate over the keys/values with this :
<div v-for="(value, key) in object">
{{ key }} - {{ value }}
</div>
You can also have the index of the current key :
<div v-for="(value, key, index) in object">
{{ key }} - {{ value }}
// if index > 0, add comma
</div>
Use default way of Vue to do this
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
Easy and simple
Object.Keys(Object) returns an array containing all the key of the object. Now you can use index to fetch the desire key -
<ul>
<li v-for="item in shoppingItems">
{{ Object.keys(item).indexOf(0) }} : {{ item.name }} - {{ Object.keys(item).indexOf(1) }} : {{ item.price }}
</li>
</ul>
Let's assume that we have a person array or list which contain person object persons:
[{name:'Suru', age:4, hairColor:'red'}, {name: 'Sofia', age:'5', hairColor:'green'}]
Now let's loop through person list and get key, value, and index
new Vue({
el: '#app',
data: {
persons: [
{name: 'Suru', age: 4, hairColor: 'red'},
{name: 'Sofia', age: '5', hairColor: 'green'}
]
}
});
<script src="https://unpkg.com/vue"></script>
<div id='app'>
<ul>
<li v-for="person in persons">
<span v-for="(value, key, index) in person">
{{key}}: {{value}} - {{index}}<br>
</span>
<br>
</li>
</ul>
</div>

Vue - check if you are on the last prop of a v-for loop

If I have the following data property:
person: {name: 'Joe', age: 35, department: 'IT'}
And wanted to loop through and output it as follows:
name: Joe, age: 35, department: IT
So far I have:
<span v-for="(val, key) in person">{{key}}: {{val}}, </span>
But this displays:
name: Joe, age: 35, department: IT,
with an extra comma on the end, how can I have it detect that it's the last prop and not show the comma? I thoughta v-show or v-if may be the solution but can't quite figure out how to make it work.
Here is one way.
<span v-for="(val,key,index) of person">
key: {{key}}, val: {{val}}, index: {{index}}
<span v-if="index != Object.keys(person).length - 1">, </span>
</span>
Here's a solution if you're looping through an array, rather than an object:
<div id="app">
<div v-for="(item, index) in items">
<div v-if="index == items.length - 1">yes</div>
{{ item }}, {{ index }}
</div>
</div>
You can also "cheat" by inserting the comma before each item, as it's easier to check for the first item (index !== 0).
<span v-for="(val, key, index) in person">
<span v-if="index !== 0">, </span>
{{key}}: {{val}}
</span>
You can do that with a computed to see if the current index (third parameter forv-if) is the last property:
computed: {
last(){
return Object.keys(this.person).length-1;
}
}
Then in your v-for:
<span v-for="(val, key, index) in person">{{key}}: {{val}}<span v-if="index !== last">, </span> </span>
Here's the JSFiddle: https://jsfiddle.net/wv2ujxvn/
This also works:
<span v-for="(value,key) in persons" :key='key'>
{{key}}: {{val}}
<span v-if="key+1 != persons.length">, </span>
</span>
A pity there is no shortcut provided by Vue.
I personally prefer using a small CSS:
<div class="list">
<span>Item 1</span>
<span>Item 2</span>
<span>Item 3</span>
</div>
.list span:not(:last-child)::after {
content: ',';
}
If you want to store the knowledge about this pattern in code instead of on Stack Overflow, you could create a component like this:
<template>
<span v-if="show"><slot></slot></span>
</template>
<script>
export default {
name: 'separator',
props: ['items', 'index'],
computed: {
show () {
return this.index !== (Array.isArray(this.items) ? this.items : Object.keys(this.items)).length - 1
}
}
}
</script>
This doesn't necessarily make the code shorted, but easier to remember:
<span v-for="(val, key, index) of person">key: {{key}}, val: {{val}}
<separator :items="person" :index="index">, </separator>
</span>