Add class to DIV based on id of object in Angular - javascript

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.

Related

How to fix ngFor/ngIf else doesn't work in angular

here's the code:
<div *ngFor="let app of application$ | async;">
<div *ngIf="app.length > 0; else noResults">
<li>{{app.id}}</li>
</div>
<ng-template #noResults>
No Results
</ng-template>
</div>
TS
application$ = new BehaviorSubject([]);
constructor() { }
ngOnInit() {
const arr = new Array();
const data = [{
id: 'room1',
name: 'Room 1'
},{
id: 'room2',
name: 'Room 2'
},{
id: 'room3',
name: 'Room 3'
}];
this.application$.next(data);
}
how to fix the else on ngFor, it when there's no data it doesn't go in noResults.
I also tried this.
HTML
<div *ngIf="application$ | async as app">
<div *ngIf="app.length !== 0; else noResults">
<div *ngFor="let data of app;let i = index;">
{{ data.name }}
</div>
</div>
<ng-template #noResults>
No Results
</ng-template>
</div>
it same error it doesn't display the noReuslts when there's no data
Your HTML should look like this
<div *ngFor="let app of application$ | async;">
<li>{{app.id}}</li>
</div>
<div *ngIf="(application$ | async).length === 0">No Results</div>
Or
<div>
<li *ngFor="let app of application$ | async;">{{app.id}}</li>
<ng-container *ngIf="(application$ | async).length === 0">No Results</ng-container>
</div>

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++;
}

how to toggle class to a single element inside a v-for

I'm new to vueJs and I'm trying to toggle a class "active" to a single element once you clicked on it. Here is my code witch toggle all element with the class material_icons. How to do it to toggle only the element clicked ?
thanks.
My hmtl :
<div v-for="(listArtist, index) in listArtists" class="col s4 center" id="art">
<p> {{ listArtist.title_short }}</p>
<p>{{ listArtist.artist.name }} </p>
<p>{{ listArtist.album.title }}</p>
<div id="margin-test">
<i class="material-icons" #click="fav(listArtist.title,listArtist.album.title,listArtist.artist.name,listArtist.id)" v-bind:class="{'active': color}">favorite_border</i>
</div>
my js :
data: {
listArtists:[],
color: false,
}
fav: function(titleTrack, album, artist, id ){
this.color = !this.color
}
The thing is you currently have only one color flag and multiple artist elements.
To make it work, you have to find a way of having, instead, multiple colors flags, one for each artist.
You could do it in basically two forms:
You can declare color as an auxiliary object and use id as key (demo 1 below).
The same would be achieved by making color an array and using index (of the v-for) instead of id.
The advantage of this approach is not to add any properties to your current artist elements.
You could also declare a color property in each artist and use it instead (demo 2 below).
This is somewhat cleaner, but does require the addition of the color property.
Demo 1 (using color as a separated object or array)
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
listArtists: [
{id: 1, title: 'title1', title_short: 'title_short1', artist: {name: 'artist.name1'}, album: {title: 'album.title1'}},
{id: 2, title: 'title2', title_short: 'title_short2', artist: {name: 'artist.name2'}, album: {title: 'album.title2'}}
],
color: {},
},
methods: {
fav: function(titleTrack, album, artist, id) {
this.$set(this.color, id, !this.color[id]);
}
}
})
.active {
color: red;
}
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div v-for="(listArtist, index) in listArtists" class="col s4 center" id="art">
<p> {{ listArtist.title_short }}</p>
<p>{{ listArtist.artist.name }} </p>
<p>{{ listArtist.album.title }}</p>
<div id="margin-test">
<i class="material-icons" #click="fav(listArtist.title,listArtist.album.title,listArtist.artist.name,listArtist.id)" v-bind:class="{'active': color[listArtist.id]}">favorite_border</i>
</div>
</div>
</div>
Demo 2 (using a color property on each element)
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
listArtists: [
{id: 1, title: 'title1', title_short: 'title_short1', artist: {name: 'artist.name1'}, album: {title: 'album.title1'}},
{id: 2, title: 'title2', title_short: 'title_short2', artist: {name: 'artist.name2'}, album: {title: 'album.title2'}}
],
color: {},
},
methods: {
fav: function(titleTrack, album, artist, id, listArtist) {
this.$set(listArtist, 'color', !listArtist.color);
}
}
})
.active {
color: red;
}
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div v-for="(listArtist, index) in listArtists" class="col s4 center" id="art">
<p> {{ listArtist.title_short }}</p>
<p>{{ listArtist.artist.name }} </p>
<p>{{ listArtist.album.title }}</p>
<div id="margin-test">
<i class="material-icons" #click="fav(listArtist.title,listArtist.album.title,listArtist.artist.name,listArtist.id,listArtist)" v-bind:class="{'active': listArtist.color}">favorite_border</i>
</div>
</div>
</div>
One Simple solution:
in #click="fav, let selectedItem=current selection (=listArtist)
then use v-bind:class="{'active': selectedItem == listArtist}"
And there is one issue in your codes, you'd better provide the unique key for each item.
new Vue({
el: "#app",
data: {
listArtists:
[
{id:1,'title_short':'Test-A',artist:{name:'Name-A'}, album:{title:'Title-A'}},
{id:2,'title_short':'Test-B',artist:{name:'Name-B'}, album:{title:'Title-B'}},
{id:3,'title_short':'Test-C',artist:{name:'Name-C'}, album:{title:'Title-C'}}
],
selectedItem: null
},
methods: {
fav: function(listArtist, titleTrack, album, artist, id ){
this.selectedItem = listArtist
}
}
});
.active{
background-color:red
}
<script src="https://unpkg.com/vue#2.0.1/dist/vue.js"></script>
<div id="app">
<div v-for="(listArtist, index) in listArtists" class="col s4 center" :key="index">
<p> {{ listArtist.title_short }}</p>
<p>{{ listArtist.artist.name }} </p>
<p>{{ listArtist.album.title }}</p>
<div id="margin-test">
<i class="material-icons" #click="fav(listArtist, listArtist.title,listArtist.album.title,listArtist.artist.name,listArtist.id)" v-bind:class="{'active': selectedItem == listArtist}">favorite_border</i>
</div>
</div>

How to custom v-for using v-if for make a class in div tag

How to correctly way use v-if when I using v-for inside?
Actually I want to add a condition when the index is 0 or first data is displayed I want to add active class
<div class="item active" v-for="(item, key, index) in slideItem" :key="item._id">
<img alt="900x500" src="http://lorempixel.com/960/720/">
<div class="carousel-caption">
<h3>{{ item.title }}</h3>
<p>{{ item.body }}</p>
</div>
</div>
and show this when the next data :
<div class="item" v-for="(item, key, index) in slideItem" :key="item._id">
<img alt="900x500" src="http://lorempixel.com/960/720/">
<div class="carousel-caption">
<h3>{{ item.title }}</h3>
<p>{{ item.body }}</p>
</div>
</div>
You can see the two examples I gave, how I combine the two loops into one by distinguishing the first index (item active) condition and so on using v-if
You can make a function isActive that determines if the index is at 0 and than
v-bind:class="{'active': isActive}"
I found the problem.. I Think you are using a key, for an array... the key is used for a dictionary.
Here is how it works:
CSS
.active {
background-color: #00ff00;
}
HTML:
<div id="output">
<div class="item" v-for="(item, index) in slideItem" :key="item._id">
<div class="carousel-caption" :class="{active: index==1}">
<h3>{{ item.title }} {{index}}</h3>
<p>{{ item.body }}</p>
</div>
</div>
</div>
Notice that I removed the key!
JS:
var vm = new Vue({
el: "#output",
data: function () {
return {
slideItem : [
{ '_id' :0, 'title':'title0' ,'body':'body 0'},
{ '_id' :1, 'title':'title1' ,'body':'body 1'},
{ '_id' :2, 'title':'title2' ,'body':'body 2'},
{ '_id' :3, 'title':'title3' ,'body':'body 3'},
{ '_id' :4, 'title':'title4' ,'body':'body 4'},
{ '_id' :5, 'title':'title5' ,'body':'body 5'}
]
}
}
});
What ...
Here is the fiddle
You could do something like:
<div class="item" v-for="(item, k) in slideItem" :key="item._id"
:class="{active: Object.keys(slideItem)[0] == k}">
<img alt="900x500" src="http://lorempixel.com/960/720/">
<div class="carousel-caption">
<h3>{{ item.title }}</h3>
<p>{{ item.body }}</p>
</div>
</div>
Object.keys(slideItem)[0] == k gets the first key of the object and then checks that the key for current iteration matches.

Computed function from Vue component Data

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>

Categories

Resources