dynamically add classes to content coming from *ngFor from an array - javascript

Im not quite sure something like this is possible but say in my html component I have an ngFor like so..
<div *ngFor="let card of cards">
... stuff in here
</div>
now say I have an array of classNames like so
classNames = [
'red',
'yellow',
'blue',
'green'
]
and inside my *ngFor I have a div like so
<div *ngFor="let card of cards">
<div [class]='...'>
<div class="card">
</div>
</div>
</div>
basically what I want to happen is for every item in the ngFor give loop through the classNames array and dynamically add it to the incoming data so for example
say I have 6 items in cards so each card needs a classname so it loops through classNames and gives it a class so like this..
<div [class]='red'>
<div class="card">
</div>
</div>
<div [class]='yellow'>
<div class="card">
</div>
</div>
<div [class]='blue'>
<div class="card">
</div>
</div>
<div [class]='green'>
<div class="card">
</div>
</div>
<div [class]='red'>
<div class="card">
</div>
</div>
<div [class]='yellow'>
<div class="card">
</div>
</div>
and so on and so forth..
how could i accomplish something like this?
EDIT
component.html
<div class="card" *ngFor="let card of cards; let i = index">
<div [class]="classNames[i%classNames.length]">
....
</div>
</div>
component.ts
export class...
classNames = [
'light-green',
'dark-green',
'aqua',
'blue',
'blue-purple',
'purple',
'purple-pink',
'purple-orange'
];

You can leverage remainder (%) operator to achieve that:
<div *ngFor="let card of cards; let i = index">
<div [class]="classNames[i%classNames.length]">
<div class="card">
{{ card }}
</div>
</div>
</div>
Ng-run Example
Update:
You should define array as follows:
classNames = [
'light-green',
'dark-green',
'aqua',
'blue',
'blue-purple',
'purple',
'purple-pink',
'purple-orange'
];
Note: i use = instead of :

Instead of randomly applying any class to any card or deciding it on view based on some %, the best way, I believe would be read it from the Cards object itself, since it is logical to have all details of a card read from the card itself.
So that view is independent of those extra stuffs.
classNames = ['red','yellow','blue','green'];
cards = [{text: 1, class: this.classNames[0]},{text: 2, class: this.classNames[1]}];
your view should simply do its task (render)
<div *ngFor="let card of cards; let i = index">
<div [class]="card.class">
<div class="card">
{{ card.text}}
</div>
</div>
</div>

Related

Javascript array with multiple objects - send to GTM - Google data layer

I have multiple products on a page each with several infos and i need to send them to google data layer on page load within an array of objects.
My script the way it is is sending one array with a object with all fields on it, what i need is to have that same array with an object per product. Here's my code and hope someone can help me. Thanks
$(function () {
var Container = (".product");
var itemName = $($(Container)).find(".item-name").text();
var itemId = $($(Container)).find(".item-id").text();
var itemPrice = $($(Container)).find(".item-price").text();
var itemBrand = $($(Container)).find(".item-brand").text();
var itemCategory = $($(Container)).find(".item-category").text();
window.dataLayer.push({
event: 'Ecommerce - Item List Views',
event_name: 'view_item_list',
view_item_list: {
items: [{
item_name: itemName,
item_id: itemId,
price: itemPrice,
item_brand: itemBrand,
item_category: itemCategory,
}]
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="product">
<div class="item-name">
<h1>Nike blue shoes</h1>
</div>
<div class="item-id">
SKU-3456
</div>
<div class="item-price">
€22.00
</div>
<div class="item-brand">
Nike
</div>
<div class="item-category">
Shoes
</div>
</div>
<div class="product">
<div class="item-name">
<h1>Adidas red shoes</h1>
</div>
<div class="item-id">
SKU-4335
</div>
<div class="item-price">
€55.00
</div>
<div class="item-brand">
Adidas
</div>
<div class="item-category">
Shoes
</div>
</div>
<div class="product">
<div class="item-name">
<h1>Nike Yellow Sandals</h1>
</div>
<div class="item-id">
SKU-9654
</div>
<div class="item-price">
€11.00
</div>
<div class="item-brand">
Nike
</div>
<div class="item-category">
Sandals
</div>
</div>
<div class="product">
<div class="item-name">
<h1>Vans Black Sneakers</h1>
</div>
<div class="item-id">
SKU-362364
</div>
<div class="item-price">
€99.00
</div>
<div class="item-brand">
Vans
</div>
<div class="item-category">
Sneakers
</div>
</div>
</div>
Instead of pushing right away, try putting the object into a variable first:
const dlObject = {
event: 'Ecommerce - Item List Views',
event_name: 'view_item_list',
view_item_list: {
items: [{
item_name: itemName,
item_id: itemId,
price: itemPrice,
item_brand: itemBrand,
item_category: itemCategory,
}]
}
}
now you can enrich it by adding more stuff into it:
dlObject.view_item_list.items.push({
item_name:'second item',
item_id:'qweqwe',price:"15",
item_brand:"foo",
item_category:"bar"
});
finally, once you're done pushing products to the items array, you push the whole thing in:
window.dataLayer.push(dlObject);

How to pass an object from ngFor to the component in angular?

I'm new to Angular and I can't really understand what is the problem I'm facing. I'm trying to pass object from an *ngFor to his component.
Here is a simple *ngFor that iterate an Array
<div class="card text-center" *ngFor="let alarm of alarms">
<div class="card-header">
....
</div>
<div class="card-body p-2">
<span class="text-secondary font-weight-bold">
Floor
<span>{{ alarm.sensor.sentinel.monitorings_sentinels[0].monitoring.patient.location[0].floor }}</span>
</span>
</div>
</div>
I want to avoid this long interpolation so I want pass the current let alarm to the component and assign three attributes to an object and display it,
customMethod(alarm) {
this.location.floor = alarm.sensor.sentinel.monitorings_sentinels[0].monitoring.patient.location[0].floor;
this.location.room = alarm.sensor.sentinel.monitorings_sentinels[0].monitoring.patient.location[0].room;
this.location.bed = alarm.sensor.sentinel.monitorings_sentinels[0].monitoring.patient.location[0].bed;
}
Here is what I expect:
<div class="card text-center" *ngFor="let alarm of alarms">
<div class="card-header">
....
</div>
<div class="card-body p-2">
<span class="text-secondary font-weight-bold">
Floor
<span>{{ location.floor }}</span>
</span>
</div>
</div>
And show the attribute's object location with string interpolation for each object alarm.
What is the best way to do this?
You want to avoid having any logic in your template (.html) file so I'll advise doing the logic in your component file.
You can prepare the alarms array before it's sent into the template.
#Component(..)
export class SomeComponent {
private _alarms;
#Input()
set alarms(alarms) {
this._alarms = alarms.map(alarm => customMethod(alarm))
}
get alarms() {
return this._alarms
}
}
function customMethod(alarm) {
return {
...alarm, // <<< remove this if you just want locations
locations: {
floor: alarm.sensor.sentinel.monitorings_sentinels[0].monitoring.patient.location[0].floor,
room: ....,
bed: ...
}
}
Then in your template
<div class="card text-center" *ngFor="let alarm of alarms">
<div class="card-header">
....
</div>
<div class="card-body p-2">
<span class="text-secondary font-weight-bold">
Floor
<span>{{ alarm.location.floor }}</span>
</span>
</div>
</div>
Create a helper method to get you the value you want to display, and then just call that from the template.
You can do anything to the object to get the value you want to display in here since it's just a funciton:
createMyString(alarm) {
return alarm.sensor.sentinel.monitorings_sentinels[0].monitoring.patient.location[0].floor;
}
Then in your template
{{createMyString(alarm)}}

Binding issue in repeat.for in aurelia

I have a list of cards that i populate, when i click on each card i want to get and display the correct items displayed for that card.
The problem i am facing is that when i return an array its not binding the correct item to the specific card.
This is my HTML
<div repeat.for="Grouping of categoryItems">
<div class="row">
<div class="col s12 m3 l3">
<div class="card blue-grey darken-1">
<div class="card-content" style="padding:10px">
<span class="card-title white-text truncate">${Grouping.name}</span>
<a if.bind="Grouping.hideDetails" class="btn-floating halfway-fab waves-effect waves-light" click.delegate="Activate(list, Grouping)"><i class="material-icons">add</i></a>
</div>
</div>
</div>
</div>
<div repeat.for="categoryGroupingTypes of categoryItemTypes">
<div class="row" if.bind="!Grouping.hideDetails">
<div class="col" style="position:absolute;padding:5%">
<div class="rotate-text-90-negative">
<span class="blue-grey-text"><b>${categoryGroupingTypes.name}</b></span>
</div>
</div>
<div repeat.for="item of categoryItemsTypes.items" class="col s12 m3 l3 ">
<div class="card-content">
<span class="card-title white-text truncate">${items.Name} ${items.Quantity}</span>
</div>
</div>
</div>
</div>
</div>
</div>
my ts
async Activate(list: ListModel[], grouping: any) {
this.categoryItemsTypes = await this.getTypes(list);
let result = this.categoryItem.filter(x => x.name == grouping.name)
if (result) {
grouping.hideDetails = false;
}
}
so this.categoryItemsTypes has the following array
0: {name: "Clothes", items: Array(3)}
1: {name: "Shoes", items: Array(2)}
so when the page loads it loads the cards as follows
then when i click on "Clothes"
i only want it to load the array associated with clothes and if "shoes" is clicked then only load that array as follows
but what is currently happening with my above code is the following
this line is where i bind the items
repeat.for="item of categoryItemsTypes.items"
how can i bind the items to the correct ${Grouping.name} as shown in picture 2?
You are in the right direction, but not complete yet.
Array assignment are not observed by aurelia.
In general, when populating arrays with a new set of elements, this is a good way:
destarray.splice(0, destarray.length, ...sourcearray);
over
destarray = sourcearray;
because the former is observed by aurelia by default and the latter is not.

How to get selected index from nested array ? Angular - Javascript

I need to get selected item but in nested array.
First check my code:
<div class="column-holder" *ngFor="let training of data.trainingExercise
{
"exerasdasd":""
},
{
"isWsadad":""
}
]
}
]
}
]
}
Now i need on click to get only selected set. Single Value!
dsadsa(e){
dsa.log(e)
dsa.dsadas = e;
}
This is good but i need only single value.
In my selectedSetValue i want to show only single value.
Right now i got values in all array.
I want only selected value and selected index. This is important selected values by index
both here
<div class="column-holder" *ngFor="let training of data.trainingExercises; let i = index;">
and here
<div class="second-box-70" *ngFor="let set of training.sets; let i = index;">
you have let i = index;. Change the second one to let j = index; or something, so they are not the same
please try this, change
<div class="second-box-70" *ngFor="let set of training.sets; let i = index;">
<div class="circle-exercise">
<div class="circle-div">
<div class="num-series">
Series
</div>
<div class="circle" (click)="selectedSet(set)">
<input [(ngModel)]="set.value" class="input-invisible-for-sets" type="type">
</div>
</div>
</div>
</div>
<p class="notes" *ngIf="selectedSetValue">
{{ this.selectedSetValue.note }}
</p>
</div>
to this
<div class="second-box-70" *ngFor="let set of training.sets; let j = index;">
<div class="circle-exercise">
<div class="circle-div">
<div class="num-series">
Series
</div>
<div class="circle" (click)="selectedSet(set,j)">
<input [(ngModel)]="set.value" class="input-invisible-for-sets" type="type">
</div>
</div>
</div>
</div>
<p class="notes" *ngIf="selectedSetValue">
{{ this.selectedSetValue.note }}
</p>
</div>
ts
selectedSet(object,index){
this.selectedSetValue = object;
}

Testing for Nested divs using Vue Test Utils

So I have this shallowMounted vue component:
<div class="card p-relative">
<div class="card-header">
<div class="card-title h4">
a cute title
<!---->
<!---->
</div>
</div>
<!---->
<div class="card-body">
<h3 class="circle" style="background-color: rgb(237, 15, 59);"></h3>
</div>
<div>
<h6 class="card-body">Value: 35</h6>
</div>
</div>
I am doing a shallowMount:
const wrapper = shallowMount(Component, { proposData: { 'shape': 'circle'}})
Later trying to find all the classes, so I can somehow find the class circle. But what I got:
const results = wrapper.classes()
console.log(results) // ['card', 'p-relative']
How to find the h3 or class 'circle' :/
Completely Noob to frontend. Please forgive for using wrong vocabulary.
As mentioned in https://vue-test-utils.vuejs.org/api/selectors.html to access direct descendants.
I did the following:
const shape = wrapper.find('.card-body > h3')
console.log(shape.classes()) //['circle']

Categories