Dynamically add DIV element with varying values - javascript

I would like to create a div card dynamically with varying values depending on the result of my API. Currently, values keep overriding each other because they all share the same element ID. Is there a way for me to dynamically add all the values into their own cards?
res.forEach(x => {
const div = document.createElement("div");
div.className = "card mb-4 box-shadow";
div.innerHTML = `
<div class="card-header">
<h4 id="serverName" class="my-0 font-weight-normal"></h4>
</div>
<div class="card-body">
<h1 id="serverPrice" class="card-title pricing-card-title"></h1>
<p id="serverTraits" class="list-unstyled mt-3 mb-4"></p>
</div>`
document.getElementById("content").appendChild(div);
document.getElementById("serverName").innerHTML = x.name
document.getElementById("serverPrice").innerHTML = x.price + '$'
document.getElementById("serverTraits").innerHTML = x.traits
})

A simple way that works with your current solution is to simply append the index or a number behind your ids
e.g
<!-- your html code becomes something like this -->
<h4 id="serverName1" class="my-0 font-weight-normal"></h4>
<h4 id="serverName2" class="my-0 font-weight-normal"></h4>
<h4 id="serverName3" class="my-0 font-weight-normal"></h4>
When retrieving, likewise, append the index
document.getElementById("serverName" + index).innerHTML = x.name
This way, all your ids will be unique.
EDIT:
The following is an example of how you can append a number behind your id
innerHTML = `
<div class="card-header">
<h4 id="serverName` + 1 + `" class="my-0 font-weight-normal"></h4>
</div>
<div class="card-body">
<h1 id="serverPrice" class="card-title pricing-card-title"></h1>
<p id="serverTraits" class="list-unstyled mt-3 mb-4"></p>
</div>`;

Why do not generate the content dynamically before appending it to the "content" element?
Simple! no ...?
look at this
div.innerHTML = `
<div class="card-header">
<h4 id="serverName" class="my-0 font-weight-normal">${x.name}</h4>
</div>
<div class="card-body">
<h1 id="serverPrice" class="card-title pricing-card-title">${x.price}</h1>
<p id="serverTraits" class="list-unstyled mt-3 mb-4">${x.traits}</p>
</div>`
document.getElementById("content").appendChild(div);

Related

i want to display the number of student from the DB into a card

Student Controller
#GetMapping("/numberStudent")
#ResponseBody
public String getStudentNumber(){
String repot = null;
repot = studentRepository.StudentsNBR();
return repot;
}
Studeent repository
#Query("select count(e) from Student ")
public String StudentsNBR();
so basicly i want to display the number of the student in a card using bootstrap
<div class="col-sm">
<div class="card bg-light" style="width: 18rem;">
<img class="card-img-top" src="https://cdn.discordapp.com/attachments/557595531526799390/1033961333584052224/spring.gif"
style="height: 180px;">
<div class="card-body">
<div class="p-1 mb-2 bg-dark text-white">
<h5 class="card-title" align="center">Spring BOOT</h5></div>
<script>
jQuery(function($) {$.number( 1234.5678, 2 );
$.ajax({
type : "GET",
url : "/numberStudent"});
</script>
</div>
</div>
</div>
Simply need to add model interface and create a variable that hold the return,
model.AddAttribute("var_name",var_name);
and go to the view and call it [th:text=${"variable-name"}]

Fire JS code for every element with the same class

I have a cart page with multiple products that have a new price. I now want to show the customer, using JS, how much he can save. For that I use my very basic knowledge of JS to write the old and new price into a variable, replace stuff I don't want in there like "€" and do my math. Then I create a new div with a certain text and how much the customer can save. What I want to achieve is that he writes that under every product.
As you can see from the snippet he only does that for the first product. I need some kind of loop or anything where he does that code for every product in the cart. So far I searched for 2 hours and couldn't find a hint. Maybe you guys and girls can help me.
var neuerpreis = document.querySelector(".price.price--reduced").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
var alterpreis = document.querySelector(".price.price--reduced .price__old").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
var difference = (alterpreis - neuerpreis).toFixed(2);
var newDiv = document.createElement("div");
var newContent = document.createTextNode(("You save ") + difference + (" €"));
newDiv.appendChild(newContent);
document.querySelector(".cart-item__price").appendChild(newDiv);
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 66,95<span class="price__old">
<span class="price__currency">€</span> 79,00</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 100,95<span class="price__old">
<span class="price__currency">€</span> 79,00</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
You can use querySelecetorAll and relative addressing
I select the .cart-item__price as the relevant container
Then I set some content as default
Note I do not convert to the string (toFixed) until I want to present it.
The INTL number formatter could also be used here
[...document.querySelectorAll(".cart-item__price")].forEach(div => {
const neuerpreis = div.querySelector(".price--reduced").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
const alterpreis = div.querySelector(".price__old").childNodes[2].nodeValue.replace(/,/g, '.').replace(/ /g, '');
const difference = alterpreis - neuerpreis;
let newContent = document.createTextNode("No savings on this product")
const newDiv = document.createElement("div");
if (difference > 0) {
newContent = document.createTextNode(("You save ") + difference.toFixed(2) + (" €"));
}
newDiv.appendChild(newContent);
div.appendChild(newDiv);
})
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 66,95
<span class="price__old">
<span class="price__currency">€</span> 79,00
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="cart-item ">
<div class="cart-item__row">
<div class="cart-item__image">
<div class="cart-item__details">
<div class="cart-item__details-inner">
<div class="cart-item__price">
<div class="price price--reduced">
<span class="price__currency">€</span> 100,95<span class="price__old">
<span class="price__currency">€</span> 79,00</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
var el = document.querySelectorAll(".test_class");
for (i = 0; i < el.length; i++) {
el[i].innerHTML = "test"+i
}
<div class="test_class">hey</div>
<div class="test_class">hey</div>
<div class="test_class">hey</div>
<div class="test_class">hey</div>
Here you go

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.

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']

Angular ngFor - restriction to show on every item

I have got following code in my component.html. ( I am new to angular )
<div class="card" *ngFor="let item of galleries;"
(mouseenter)=" setBackground(item?.image?.fullpath)"
(mouseover)="showCount = true; getImagesCount(item.path);" (mouseleave)="showCount = false">
<img class="card-img-top" [routerLink]="['/'+item.path]"
[src]="item?.image?.fullpath ? path + '0x156/' + item?.image?.fullpath : defaultImage"
alt="Card image cap">
<div class="card-block">
<h4 class="card-title imagesCount"></h4>
<h4 class="card-title title">{{item.name}}</h4>
<img class="closeIcon" src="../../../assets/images/close.png" alt="" (click)="removeGallery(item);">
<span class="animated fadeInUp" *ngIf="showCount">{{imagesCount}}</span>
</div>
</div>
Down in the code i have *ngIf="showCount where i am trying to show how many images gallery have. But issue is that it is shown on every card, but i want it to show only on current card that i enter my mouse with.
You should specify your *ngIf in:
<span class="animated fadeInUp" *ngIf="showCount">{{imagesCount}}</span>
because actually you will get for every item in your galleries list.
Here is an idea, how you can specify that:
Step 1: Add new variable to your component.ts
currentItem: number;
Step 2: add index to your ngFor
*ngFor="let item of galleries; let index = index;"
Step 3: Extend your (mouseover) and (mouseleave) events
Add currentItem and fill with data.
(mouseover)="showCount = true; currentItem = index; getImagesCount(item.path);"
(mouseleave)="showCount = false; currentItem = null;"
Step 4: Change you *ngIf in span with itemsCount
<span class="animated fadeInUp" *ngIf="showCount && currentItem == index">{{imagesCount}}</span>
Now you have a spicified solution.
I would suggest you to create an extra key i.e. showCount inside item object.
item = {
...,
showCount: false
}
than use that key for showing and hiding showCount in the HTML.
<div class="card" *ngFor="let item of galleries;"
(mouseenter)=" setBackground(item?.image?.fullpath)"
(mouseover)="item[showCount] = true; getImagesCount(item.path);"
(mouseleave)="item[showCount] = false">
<img class="card-img-top" [routerLink]="['/'+item.path]"
[src]="item?.image?.fullpath ? path + '0x156/' + item?.image?.fullpath : defaultImage"
alt="Card image cap">
<div class="card-block">
<h4 class="card-title imagesCount"></h4>
<h4 class="card-title title">{{item.name}}</h4>
<img class="closeIcon" src="../../../assets/images/close.png" alt="" (click)="removeGallery(item);">
<span class="animated fadeInUp" [hidden]="item[showCount]">{{imagesCount}}</span>
</div>
</div>
I would approach this by making your 'showCount' variable into an array, and comparing *ngIf to the array value:
Some small tweaks:
<div class="card" *ngFor="let item of galleries; let idx=index">
....
(mouseover)="showCount[idx]=true
(mouseleave)="showCount[idx]=false
</div>
...
<span class="animated fadeInUp" *ngIf="showCount[idx]">

Categories