total basket reactive vuejs - javascript

Is it possible to make the total reactive? for example, in my basket I have two articles for a price of 18 €, if I add an article I want the total to change without updating the page.
my property calculate total returns me for two options: 14,0012,00 I would have liked it to calculate the price of the two options dynamically: 14,00 + 12,00 = 26
thank you for help
<template>
<div>
<div >
<div >
<u>
<li v-for="item in shop" :key="item.id">
{{ item.label}} : {{ item.cost }}€
</li>
</u>
<button #click="addItem">Add</button>
</div>
<div >
<u>
<li v-for="item in shop" :key="item.id">
{{ item.label}} : {{ item.cost }}€
</li>
</u>
</div>
<p>{{ total}}</p>
</div>
</div>
</template>
<script>
computed:{
totalbasket(){
let total = 0
this.shop.forEach(item=>{
total += item.cost
})
return total
}
}
</script>

It looks like the problem is your item.cost is a string, not a float.
Parsing the cost to floats before adding them might do the trick:
totalbasket(){
let total = 0
this.shop.forEach(item=>{
total += parseFloat(item.cost)
})
return total
}
And at the moment you have {{total}} in your template. You probably want to change this to {{totalBasket}}.
As mentioned by tony19 javascripts parseFloat function does not recognize commas as decimal points. There's a question about how to solve it here.

I would add an Add Button to each item you want to add and then call addItem(item). It would be something like this:
...
<li v-for="item in shop" :key="item.id">
{{ item.label}} : {{ item.cost }}€
<button #click="addItem(item)">Add</button>
</li>
Then, the addItem method adds the item, which would trigger totalbasket:
methods: {
addItem(item) {
this.shop.push(item)
},
...
}
And in your template, you should print totalbasket instead of total:
<p>{{ totalbasket }}</p>
This should do it.

Related

How to increment a loop in Vue

I've got a multi-object array and I'd like to have it loop through a particular group of objects.
This is my code so far
<template>
<div>
<h1>My Test App</h1>
<button v-on:click="getHockeyData">Get Team Data</button>
<div v-for="hockeyData in hockeyDataList" :key="hockeyData.id" >
<p>{{ hockeyDataList.teams[0].roster.roster[1].person.fullName }}</p>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: "Weather",
data() {
return {
hockeyDataList: []
};
},
methods: {
getHockeyData() {
axios.get("https://statsapi.web.nhl.com/api/v1/teams/21?expand=team.roster").then(response => (this.hockeyDataList = response.data));
}
}
};
</script>
I know the loop won't work in it's current state. The portion of my output within the loop that I need to increment is roster[1] - I'm new to Vue so not sure how to use the v- commands to increment that 1 until there are no more instances of it.
Any help or feedback would be greatly appreciated!
Just loop over the others, really you want to start from teams as that's the way the JSON is structured
Example using various parts of the JSON, view the file for others.
<div v-for="team in hockeyDataList.teams" :key="team.id">
<h1>{{ team.name }}</h1>
<div>{{ team.venue.name }}, {{ team.venue.city }}</div>
<div>Created in: {{ team.firstYearOfPlay }}</div>
<div>Division: {{ team.division.name }} - Conference: {{ team.conference.name }}</div>
<h2>Roster</h2>
<div v-for="player in team.roster.roster" :key="team.id + '-' + player.person.id">
<h3>{{ player.person.fullName }}</h3>
<div>
Number: {{ player.jerseyNumber }} - Position: {{ player.position.name }} {{ player.position.type }}
</div>
</div>
</div>
<div v-for="team in hockeyDataList.teams" :key="team.id" >
<p v-for="roster in team.roster.roster :key="roster.id">
{{ roster.person.fullName }}
</p>
</div>
It's not necessary, but if you want to, you can get index in a v-for as well:
<div v-for="(team, index) in hockeyDataList.teams" :key="team.id" >
<p>
{{ hockeyDataList.teams[index].roster.roster[1].person.fullName }}
</p>
</div>
v-for increments the index automatically for you. The problem is that the api returns a json and not an array we can iterate on. By looking at the api response, we can see that teams is the array we can iterate on.
<v-for="(team, i) in hockeyDataList.teams" :key="i">
where index automatically increments until the end of list. We can then iterate through the roster.
<v-for="(roster, j) in team.roster.roster" :key="j">
Putting it all together
<div v-for="(team, i) in hockeyDataList.teams" :key="i">
<div v-for="(roster, j) in team.roster.roster" :key="j">
<p>{{ hockeyDataList.teams[i].roster.roster[j].person.fullName }}</p>
</div>
</div>

how to add :key in v-for with multiple divs

I want to make v-for loop without any html element so I decided to use <template as parent. I don't know to assign :key for this loop. I can't assign it to template and to every div inside loop. Any ideas?
<template
v-for="{ id, text, option, percentage, value } in reports"
>
<div class="table-row__index">
{{ id }}
</div>
<div class="table-row__title">
<p>{{ text }} - <strong>{{ option }}</strong></p>
</div>
<div class="table-row__info">
{{ percentage }}%
</div>
<div class="table-row__info">
{{ value }}
</div>
</template>
As a good practice we should always have a parent element inside. But due to your constraints, it's okay to use for loop on template as given in official docs
https://v2.vuejs.org/v2/guide/list.html#v-for-on-a-lt-template-gt
In this case, any keys have to be added to child elements/components and this is what officially recommended.
See this example and please add keys to your div's inside template.
new Vue({
el: '#app'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<template v-for="n in 5">
<span :key="'number' + n">{{ n }}</span>
<span :key="'dot' + n">. </span>
</template>
</div>
you just can't have the for loop in your template. The for loop directive is only allowed to be inside the first child component ( or root component) inside your template.
Here is an example of how you can render your loop:
<template>
<div class="cant-have-for-loop-this-is-the-root-component">
<div v-for="{ id, text, option, percentage, value } in reports" :key="{id}">
<div class="table-row__index">
{{ id }}
</div>
<div class="table-row__title">
<p> {{ text }} - <strong>{{ option }}</strong></p>
</div>
<div class="table-row__info">
{{ percentage }}%
</div>
<div class="table-row__info">
{{ value }}
</div>
</div>
</div>
</template>
This runs soomthly, and with no hesitations. And renders with no styling as this screenshots depicts:
Hope this answers what you want to achieve.

Get lowest price from vue js array

I have this array which loops through all the trips for a listing.
<span v-for="price in listing.trips">
<div class="price">{{ price.cost }} </div>
</span>
Is it possible to apply a filter, just to take the lowest priced trip?
I tried:
<span v-for="price in listing.trips">
<div class="price">{{ Math.min(price.cost) }} </div>
</span>
Maybe you can just just create computed property?
new Vue({
....
computed: {
cheapestTrip: function () {
return this.listing.trips.sort(trip=>trip.price)[0];
}
}
});
And then use it like this:
<span>
<div class="price">{{ cheapestTrip }} </div>
</span>
You can also omit [0] if you want to have array. In this case use your view snippet.

Looping over multiple json arrays with Angular

I have a large JSON file structured like the following which I'm trying to loop over in Angular:
{
"subject1":[
{
"title":"titlehere",
"info":"infohere."
}],
"subject2":[
{
"title":"titlehere",
"info":"infohere."
}],
"subject3":[
{
"title":"titlehere",
"info":"infohere."
}]
}
I want my page to grab the key for each 'category' and then the display the title underneath it. I'm able to get the key to display but I can't seem to figure out how to grab the string for each title. This is what I have in my HTML:
<div ng-repeat="(key, value) in faqs">
<h3>{{ key }}</h3>
<ul>
<li>{{ value }}</li>
</ul>
</div>
I'm not sure what I should be using instead of {{ value }} which grabs nothing but the entire JSON file as a string. I tried {{ value.title }} and still had no luck.
Any suggestions?
Use {{ value[0].title }}
your code be
<div ng-repeat="(key, value) in faqs">
<h3>{{ key }}</h3>
<ul>
<li ng-repeat="val in value">{{ val.title }}</li>
</ul>
</div>

Sorting a JSON response in Angular by keys

Alright, I've been stuck on this one for a while and can't find an adequate solution out there. Basically, I've grouped the posts by date server-side and I want to sort the groups by decending date in Angular. I'm assuming a custom filter is the way to go but I haven't been able to get it to work.
Here's some of the code:
JSON Response:
{"September 20th":[{"id":5,"title":"Test 1","url":"www.google.com","tagline":"Test tagline 1","created_at":"2014-09-20T19:30:44.672Z","updated_at":"2014-09-20T19:30:44.672Z","vote_count":5}],"September 21st":[{"id":6,"title":"Test 2","url":"www.google.com","tagline":"Test tagline 2","created_at":"2014-09-21T00:00:00.000Z","updated_at":"2014-09-20T19:32:41.409Z","vote_count":8}]}
HTML:
<section ng-controller='MainController'>
<ul ng-repeat="(date, posts) in postList | filter?">
<h1>{{ date }}</h1>
<li ng-repeat='post in posts'>
<p>{{ post.vote_count }}</p>
<button ng-click='upvote(post)' ng-disabled='!currentUser || hasVoted(post.id)'></button>
{{ post.title }}
</li>
</ul>
</section>
This displays the information perfectly, just in the incorrect order of dates.
I appreciate any help you can give me!
It's a bit hacky, but it works:
Example
Html:
<section ng-controller='MainController'>
<ul ng-repeat="posts in postList | orderObjectBy:'created_at':true">
<h1>{{ posts.__originalKey }}</h1>
<li ng-repeat='post in posts'>
<p>{{ post.vote_count }}</p>
<button ng-click='upvote(post)' ng-disabled='!currentUser || hasVoted(post.id)'></button>
{{ post.title }}
</li>
</ul>
</section>
CustomFilter:
.filter('orderObjectBy', function() {
return function(items, field, reverse) {
var filtered = [];
angular.forEach(items, function(item, key) {
item.__originalKey=key;
filtered.push(item);
});
filtered.sort(function (a, b) {
return (a[field] > b[field] ? 1 : -1);
});
if(reverse) filtered.reverse();
return filtered;
};
})

Categories

Resources