Computed function from Vue component Data - javascript

I have the following Vue component and data:
Vue.component('receipt', {
template: '#receipt-template',
data: function() {
return {
tip: 8.50
};
},
computed: {
subtotal: function() {
return this.sales.price;
console.log(this.sales.price);
}
},
props: ['header', 'date', 'sales' ]
})
new Vue({
el: '#content',
data: {
sales1: [
{amount: 1, desc: 'A book title', price: 13.99},
{amount: 3, desc: 'An espresso title', price: 5.00},
{amount: 6, desc: 'A drink title', price: 4.25},
{amount: 2, desc: 'A pastrt', price: 3.99}
],
sales2: [
{amount: 1, desc: 'A title', price: 9},
{amount: 2, desc: 'An title', price: 0},
{amount: 3, desc: 'A title', price: 5},
{amount: 4, desc: 'A ', price: 99}
]
}
})
And the following template:
<div class="page page2 current">
<!-- Call our custom receipt vue component -->
<receipt header="Between the Covers & Grinders Café" date="Sept. 23, 2016 10:52 am" :sales="sales1"></receipt>
<receipt header="Between the Covers & Grinders Café" date="Sept. 25, 2016 3:08 pm" :sales="sales2"></receipt>
<div class="clearfix"></div>
</div><!--end page2-->
<template id="receipt-template">
<div class="receipt">
<div class="receipt-header">
<h2>{{ header }}</h2>
</div><!--end receipt-header-->
<div class="receipt-body">
<div class="receipt-labels">
<p>Sales</p>
<p>{{ date }}</p>
<div class="clearfix"></div>
</div><!--end receipt-labels-->
<div class="receipt-sales">
<div class="receipt-sale-row" v-for="sale in sales">
<p>{{ sale.amount }}</p>
<p>{{ sale.desc }}</p>
<p class="sale-price">${{ sale.price }}</p>
</div><!--end receipt-sale-row-->
</div><!--end receipt-sales-->
<div class="receipt-subtotals">
<p>Subtotal</p>
<p>{{ subtotal }}</p>
<p>Tax</p>
<p>$2.64</p>
<div class="clearfix"></div>
</div><!--end subtotals-->
<div class="receipt-totals">
<p>Tip</p>
<p>{{ tip }}</p>
<p>Total</p>
<p></p>
<div class="clearfix"></div>
</div><!--end totals-->
<div class="receipt-card">
<p>Visa 1825</p>
<p>$41.25</p>
<div class="clearfix"></div>
</div><!--end card-->
</div><!--end receipt-body-->
</div><!--end receipt-->
</template>
I can't figure out how to compute the 'subtotal'. What I need to do is have the computed function 'subtotal' return the total of all prices for each 'sales' object. What am I doing wrong?

You need to add up all the price components in this.sales.
subtotal: function() {
let result = 0;
this.sales.forEach((sale) => result += sale.price);
return Math.round(100 * result) / 100;
}
Vue.component('receipt', {
template: '#receipt-template',
data: function() {
return {
tip: 8.50
};
},
computed: {
subtotal: function() {
let result = 0;
this.sales.forEach((sale) => result += sale.price);
return Math.round(100 * result) / 100;
}
},
props: ['header', 'date', 'sales']
});
new Vue({
el: '.page.current',
data: {
sales1: [{
amount: 1,
desc: 'A book title',
price: 13.99
}, {
amount: 3,
desc: 'An espresso title',
price: 5.00
}, {
amount: 6,
desc: 'A drink title',
price: 4.25
}, {
amount: 2,
desc: 'A pastrt',
price: 3.99
}],
sales2: [{
amount: 1,
desc: 'A title',
price: 9
}, {
amount: 2,
desc: 'An title',
price: 0
}, {
amount: 3,
desc: 'A title',
price: 5
}, {
amount: 4,
desc: 'A ',
price: 99
}]
}
});
.receipt-subtotals p,
.receipt-labels p,
.receipt-sale-row p,
.receipt-totals p {
display: inline-block;
margin: 1rem;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div class="page page2 current">
<!-- Call our custom receipt vue component -->
<receipt header="Between the Covers & Grinders Café" date="Sept. 23, 2016 10:52 am" :sales="sales1"></receipt>
<receipt header="Between the Covers & Grinders Café" date="Sept. 25, 2016 3:08 pm" :sales="sales2"></receipt>
<div class="clearfix"></div>
</div>
<!--end page2-->
<template id="receipt-template">
<div class="receipt">
<div class="receipt-header">
<h2>{{ header }}</h2>
</div>
<!--end receipt-header-->
<div class="receipt-body">
<div class="receipt-labels">
<p>Sales</p>
<p>{{ date }}</p>
<div class="clearfix"></div>
</div>
<!--end receipt-labels-->
<div class="receipt-sales">
<div class="receipt-sale-row" v-for="sale in sales">
<p>{{ sale.amount }}</p>
<p>{{ sale.desc }}</p>
<p class="sale-price">${{ sale.price }}</p>
</div>
<!--end receipt-sale-row-->
</div>
<!--end receipt-sales-->
<div class="receipt-subtotals">
<p>Subtotal</p>
<p>${{ subtotal }}</p>
<p>Tax</p>
<p>$2.64</p>
<div class="clearfix"></div>
</div>
<!--end subtotals-->
<div class="receipt-totals">
<p>Tip</p>
<p>{{ tip }}</p>
<p>Total</p>
<p></p>
<div class="clearfix"></div>
</div>
<!--end totals-->
<div class="receipt-card">
<p>Visa 1825</p>
<p>$41.25</p>
<div class="clearfix"></div>
</div>
<!--end card-->
</div>
<!--end receipt-body-->
</div>
<!--end receipt-->
</template>

Related

How can I render two object in div?

I have 2 objects with data and I need to restruct the rendering in html.
This is what I get:
but this is what I need to obtain:
Black box is the *ngFor of articles object, respectively red one is *ngFor of adsContainer object
<div *ngFor="let article of articles; let i = index;">
<mat-card class="card">
<div>
<a class="title">
{{article.title}}
</a>
<a>
<p>{{article.content}}</p>
</a>
</div>
</mat-card>
<div class="container" *ngIf="(i % 7) === 6">
<div *ngFor="let data of adsContainer">
<div>
<h1>{{data.value}}</h1>
</div>
</div>
</div>
</div>
public adsContainer: any = [
{ id: '1', value: 'text value here' },
{ id: '2', value: 'text value here' },
{ id: '3', value: 'text value here' }
]
public articles: any = [
{ id: '1', title: 'title value here', content: 'content here' },
{ id: '2', title: 'title value here', content: 'content here' },
{ id: '3', title: 'title value here', content: 'content here' },
........
{ id: '20', title: 'title value here', content: 'content here' },
]
Your issue is that you add your ads containers in a loop
<div class="container" *ngIf="(i % 7) === 6">
<!-- this loop here -->
<div *ngFor="let data of adsContainer">
<div>
<h1>{{data.value}}</h1>
</div>
</div>
</div>
what you want is to add only one ad container at a time, in order to do that, you have to rmove the loop
In order to have the three ads show, you'll have to do some math to get the ad index from the article index
something like this :
<div class="container" *ngIf="(i % 7) === 6">
<div>
<h1>{{adsContainer[mathFloor(i / 7)].value}}</h1>
</div>
</div>
note that Math is not available in angular templates, you'll have to redefine floor as a component method
function mathFloor(val) {return Math.floor(val)}
Try to use directly the array , also when you call
adsContainer[(parseInt(i / 6)-1)% adsContainer.length, it will always restart the index:
<div *ngFor="let article of articles; let i = index;">
<mat-card class="card">
<div>
<a class="title">
{{article.title}}
</a>
<a>
<p>{{article.content}}</p>
</a>
</div>
</mat-card>
<div class="container" *ngIf="(i % 7) === 6">
<div>
<div>
<h1>{{adsContainer[(parseInt(i / 6)-1)%adsContainer.length].value}}</h1>
</div>
</div>
</div>
</div>

Javascript - loop to create list of cards

HTML and simple JS (no react / vue).
I need to do a list of cards and would like to do a loop to avoid repeating the html.
My current code :
<div id="products-cards-container">
<div class="products-cards">
<div class="product-header">
<img src="../assets/img/image1.png"/>
</div>
<div class="product-content">
<h4>title 1</h4>
<p>super content 1</p>
</div>
<button class="info-button">+ info</button>
</div>
<div>
<div class="product-header">
<img src="../assets/img/cards/products/image2.png"/>
</div>
<div class="product-content">
<h4>title 2</h4>
<p>super content 2</p>
</div>
<button class="info-button">+ info</button>
</div>
<div>
<div class="product-header">
<img src="../assets/img/cards/products/image-3.png"/>
</div>
<div class="product-content">
<h4>title 3</h4>
<p>blablablablbalbalbabla blablaba</p>
</div>
<button class="info-button">+ info</button>
</div>\
</div>
I am trying to return html
script.js
const valuesCards = [
{
image: '../img/image1.png',
title: 'title 1',
content: 'super content 1',
},
{
image: '../img/image2.png',
title: 'title 2',
content: 'super content 2'
},
{
image: '../img/image-3.png',
title: 'title3',
content: 'blablablablbalbalbabla blablaba'
},
]
creating a function that inserts the list of cards in the .products-cards div :
function returnCards() => {
----- AND HERE I AM STUCK
(as well, all tries I did with a simple array / object returned only the last info) ----
}
Use Array.prototype.map function and a template literal.
const container = document.getElementById('products-cards-container');
const valuesCards = [{
image: '../img/image1.png',
title: 'title 1',
content: 'super content 1',
},
{
image: '../img/image2.png',
title: 'title 2',
content: 'super content 2'
},
{
image: '../img/image-3.png',
title: 'title3',
content: 'blablablablbalbalbabla blablaba'
},
]
function returnCards(valuesCards) {
return "<div class=\"products-cards\">" + valuesCards.map(valuesCard => `
<div>
<div class="product-header">
<img src="${valuesCard.image}"/>
</div>
<div class="product-content">
<h4>${valuesCard.title}</h4>
<p>${valuesCard.content}</p>
</div>
<button class="info-button">+ info</button>
</div>`).join('') + "</div>";
}
container.innerHTML = returnCards(valuesCards);
<div id="products-cards-container"></div>
You can do it this way
const valuesCards = [
{
image: '../img/image1.png',
title: 'title 1',
content: 'super content 1',
},
{
image: '../img/image2.png',
title: 'title 2',
content: 'super content 2'
},
{
image: '../img/image-3.png',
title: 'title3',
content: 'blablablablbalbalbabla blablaba'
},
];
let cardHTML = '';
valuesCards.map(element => {
cardHTML += '<div> \
<div class="product-header"> \
<img src="'+element.image+'"/> \
</div> \
<div class="product-content"> \
<h4>'+element.title+'</h4> \
<p>'+element.content+'</p> \
</div> \
<button class="info-button">+ info</button> \
</div> \
';
});
document.getElementsByClassName('products-cards')[0].innerHTML = cardHTML;
<div id="products-cards-container">
<div class="products-cards">
</div>
</div>
const valuesCards = [
{
image: '../img/image1.png',
title: 'title 1',
content: 'super content 1',
},
{
image: '../img/image2.png',
title: 'title 2',
content: 'super content 2'
},
{
image: '../img/image-3.png',
title: 'title3',
content: 'blablablablbalbalbabla blablaba'
},
]
valuesCards.map(card=> {
var cardDiv = document.createElement('div');
cardDiv.innerHTML = `
<div class="product-header">
<img src="${card.image}"/>
</div>
<div class="product-content">
<h4>${card.title}</h4>
<p>${card.content}</p>
</div>
<button class="info-button">+ info</button>`
document.getElementsByClassName('products-cards')[0].appendChild(cardDiv);
})
<div id="products-cards-container">
<div class="products-cards">
</div>
</div>
You need to do a "for loop" that iterates over your valuesCards object and for each value return an html template an inject into the desired element in DOM.
For example:
// Define the object
const valuesCards = [
{
'image': '../img/image1.png',
'title': 'title 1',
'content': 'super content 1',
},
{
'image': '../img/image2.png',
'title': 'title 2',
'content': 'super content 2'
},
{
'image': '../img/image-3.png',
'title': 'title3',
'content': 'blablablablbalbalbabla blablaba'
}
]
// Identify the DOM element to store cards
cardsContainer = document.querySelector('#products-cards-container');
// Create a loop that iterates over valuesCards object
for (let value of Object.values(valuesCards)) {
console.log(value.title);
// Create an element to store new card content
let newCard = document.createElement('DIV');
// Add products-cards class to new element
newCard.classList.add('products-cards');
// Create a multiline string template with current values each time
cardHtml = `
<div class="">
<div class="product-header">
<img src="${value.image}"/>
</div>
<div class="product-content">
<h4>${value.title}</h4>
<p>${value.content}</p>
</div>
<button class="info-button">+ info</button>
</div>
`;
// Append the new element to the cardsContainer element in DOM
cardsContainer.appendChild(newCard);
// Inject the template html on DOM's new append item
newCard.innerHTML = cardHtml;
}
Important!! create a div element with the id="products-cards-container" in the html where you want to print the cards.

Add class to DIV based on id of object in Angular

I want to add a class to a div based on the id of a field in a object. So far my code is not working for some reason?
<ng-container *ngFor="let item of cards">
<div class="card event-card mb-3">
<div
class="card-body"
[ngClass]="{
'card-main': id === '1',
'card-main2': id === '2'
}"
>
<p class="card-title">{{ item.title }}</p>
{{ item.date }}, {{ item.time }}
{{ item.id }}
</div>
</div>
</ng-container>
public cards = [
{
title: "Example title",
date: "Jan 25, 2025",
time: "11:22am",
typeEvent: "Concert",
id: "1"
},
{
title: "Example title",
date: "Feb 27, 2029",
time: "14:22pm",
typeEvent: "Show",
id: "2"
}
];
You have to use item.id instead of just id for the comparison.

grocery cart on Angular

I create add-to-cart app.
Want to click each item and add it to cart.
But firstly I need to click button 'add to cart' and increase its value with every click.
As I added ng-repeat, I don't know how to write a function that will be responsible for adding separate item.
angular.module('TransactionApp', [])
.controller('TransactionsCtrl', function($scope) {
$scope.title = 'Online-store';
$scope.itemsArray = [
{ price: 50, name: "Whey protein", img: 'img/item-1.png', quantity: 0},
{ price: 60, name: "Protein bar", img: 'img/item-2.png', quantity: 0 },
{ price: 35, name: "BCAA", img: 'img/item-3.png', quantity: 0 },
{ price: 50, name: "Whey protein", img: 'img/item-1.png', quantity: 0 },
{ price: 60, name: "Protein bar", img: 'img/item-2.png', quantity: 0 },
{ price: 80, name: "BCAA", img: 'img/item-3.png', quantity: 0 }
];
// $scope.count = 0;
$scope.addTo = function(){
}
});
here is html:
<h2 class="title">{{title}} <i class="em em-shopping_bags"></i></h2>
<div class="container">
<div class="row">
<div class="col-lg-4 col-md-2 col-sm-6">
<div class="card" style="width: 18rem;" ng-repeat='item in itemsArray'>
<img class="card-img-top" ng-src={{item.img}} alt="Card image cap">
<div class="card-body">
<h5 class="card-title"></h5>
<p class="card-text">{{item.name}}</p>
<p class="price">{{ item.price | currency }}</p>
<i class="em em-shopping_trolley"></i> Add to cart <span class="number">{{ item.quantity }}</span>
</p>
</div>
</div>
</div>
</div>
</div>
Pass the item to controller with addTo(item):
<a href="#" class="btn btn-warning" ng-click="addTo(item)">
<i class="em em-shopping_trolley"></i>
Add to cart
<span class="number">{{ item.quantity }}</span>
</a>
after your addTo accepts a parameter:
$scope.addTo = function(item){ // 'item' is a reference to an element in itemsArray
item.quantity++;
}
I believe each of your item in view has its own Add to Cart Button against it and I also believe you want to increase the quantity property of each of the item each time a user clicks the button against that item.
For that all you have to do is pass the item to addTo() method like :-
<i class="em em-shopping_trolley"></i> Add to cart <span class="number">{{ item.quantity }}</span>
and modify the method definition in controller
$scope.addTo = function(var item){
item.quantity++;
}

Controller data set another page in angular

After that clicked user.html list. I have to show clicked product data in productDetail.html file.
ProductController.js
$scope.selectedProduct = function(product)
{
console.log(product.post_title);
}
user.html
<div ng-repeat="p in users.products | filter:searchBox">
<a href="#/{{$index}}/{{$index}}" ng-mouseover="selectedProduct(p)" ng-click="selectedProduct(p)" style="text-decoration:none;">
<ion-item class="item widget uib_w_109 d-margins item-button-left" data-uib="ionic/list_item_button" data-ver="0">
{{p.post_title}} <br>
</ion-item>
</a>
</div>
productDetail.html
<div class="users">
<a>
<ion-item data-uib="ionic/list_item_button" data-ver="0">Product Name : {{clickedProduct.post_title}} <br>
Product Id : {{selected.product}}<br>
Post Date : {{product.post_title}}
</ion-item>
</a>
</div>
Need more Clarification, whether both HTML are shown in same view or different on product click.
here is a Plunker i made understanding your question and comments.
https://plnkr.co/edit/Ii52KZkjpNndmAMvQQYU?p=preview
$scope.products = [{
ID: 'P1',
post_title: 'product 1',
post_date: '20th July 2016',
post_author: 'John Doe'
}, {
ID: 'P2',
post_title: 'product 2',
post_date: '29th July 2016',
post_author: 'Jane Doe'
}, {
ID: 'P3',
post_title: 'product 3',
post_date: '12th July 2016',
post_author: 'John William'
}];
$scope.selectedProduct = {};
$scope.selectProduct = function(index){
$scope.selectedProduct = $scope.products[index];
};
and here is the HTML
<div>
Product List
<div ng-repeat="product in products">
<ion-item>
{{product.post_title}}
<button ng-click="selectProduct($index)">select</button>
<br>
</ion-item>
</div>
</div>
<div ng-include="'product.html'"></div>
the other HTML will pick the same angular controller.

Categories

Resources