How to display just one element with same id - javascript

This is my first question at stack overflow
i just wanted to know a simple solution for the following case
<div *ngFor="let d of w.event">
<div class="date" id="d.date" >
<p>
<span style="font-size:1.75em">{{d.date | date:'dd'}}</span>
<br>
<strong> {{d.date | date:'EEE'}}</strong>
</p>
</div>
the looped div can have the same id
I just want to display the first div with a particular date and ignore the rest
can this be achieved with CSS or JavaScript

You can't use the same id on two elements. It's one of the few restrictions on ids.
You can use a class:
<div class="show">Yes</div> <div class="show">No</div>
...and then show either the first or second by using index 0 or index 1 after getting a list of matching elements:
var list = document.querySelectorAll(".show");
list[0].style.display = "none"; // Hides the first one
// or
list[1].style.display = "none"; // Hides the second one
Some other thoughts:
1. Rather than using style.display as I did above, you might add a class that hides the element.
2. You might use separate ids (or classes) for the elements so you don't need to index, e.g.:
<div id="show-yes">Yes</div> <div id="show-no">No</div>
then
document.getElementById("show-yes").style.display = "none";
// or
document.getElementById("show-no").style.display = "none";
On all browsers in my experience, you can do the first thing above (with querySelectorAll) with your invalid HTML with a selector like "[id=show], but don't. Fix the HTML instead.
In your question update, you show:
<div *ngFor="let d of w.event">
<div class="date" id="d.date" >
...
You've said you're aware of the fact you can't have multiple elements with the same id, so why code that? You can easily give them unique ids:
<div *ngFor="let d of w.event; let i = index">
<div class="date" id="d.date{{i}}" >
...

First of all, in HTML ID is a unique selector so one ID can be associate with only one element. if you want to achieve your desired functionality you have to assign different id for both DIV. and use javascript to hide and show DIV
<div id="showYes">Yes</div> <div id="showNo">No</div>

If you want to show one at a time you can go with *ngIf , as it will show only one at a time
<div id="show" *ngIf='your_status'>Yes</div>
<div id="show" *ngIf='!your_status'>No</div>
After your question update , you can create custom filter that will only return unique date , so only first unique date will be shown
// CREATE A PIPE FILTER :
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({name: 'checkUniqueDate'})
export class UniqueDatePipe implements PipeTransform {
transform(dataArray) {
let dates = [];
return dataArray.filter(data => {
return if(dates.indexOf(data.date) === -1) {
dates.push(data.date);
return true;
} else {
return false;
}
});
}
}
// TEMPLATE SIDE :
<div *ngFor="let d of (w.event | checkUniqueDate )">

Add the date in class also, then you can try below code
.YOUR_DATE{
display:none
}
.YOUR_DATE:first-child{
displany:inline
}

Related

Filtering products in JavaScript

so I am trying to filter products when clicking a button, there is an existing class "product-card--hide" that has javascript to hide the products when they have the class.
All the products have the class all and then some have other classes depending on their characteristics, so I want to filter based on those classes.
I have created this function:
function filterdeposit(){
const products = document.querySelectorAll('.all');
if ((!products.classList.contains('.deposit')) && (!products.classList.contains('.product-card--hide'))){
products.addClass('.product-card--hide');
} else if (products.classList.contains('.deposit') && products.classList.contains('.product-card--hide')){
products.removeClass('.product-card--hide') ;
} else {
products = products;
}
}
and then I have products and buttons similar to this:
<body>
<button class="button" onclick = "filterdeposit()"> Deposit</button>
<div class= "all deposit";>Deposit</div>
<div class= "all something";>Deposit</div>
<div class= "all somethingelse";>Deposit</div>
</body>
Obviously this example is just to filter for the deposit class but will have separate functions for each of the other products. Here when clicking deposit button it must select all products with class '.all' and then check which of those also have the '.deposit' class and '.product-card__hide' class and remove '.product-card__hide' class if that is true but if they dont contain 'deposit' or 'product-card__hide' then it must add it so the products get hidden. Nothing must happen otherwise (the last else) wasn't sure what to do in that case.
Unfortunately, this isn't working for me, so any advice would be greatly appreciated.
You need to loop through the elements, removing and adding classing as needed, for example by using a forEach, like this:
function filterdeposit() {
const products = document.querySelectorAll(".all");
products.forEach((prod) => {
prod.classList.remove("product-card-hide");
if (!prod.classList.contains("deposit")) {
prod.classList.add("product-card-hide");
}
});
}

Why nested array dynamic update is not working in my case

Hi i have a problem with nested array dynamic update as shown in below image
Here is a steps to re-produce the problem
click on Add Likes button it will add likes for eg New Apple
my default like is Mango
click on Add about button it will add next row (Mango is not appeared) click on Add Likes to see the problem.
For reducing code readability i have put helper function into a mixin file called mixin.js
Expectation: i can add any number of Add about and Add Likes(with default value Mango)
Here is my code: https://codesandbox.io/s/musing-hawking-di4d3?file=/src/App.vue
First, you don't need a nested array for the tags property.
Use:
getLikesTemplate() {
let year = this.year;
let template = {
id: this.getUniqueId(),
like: `I'm ${year} Old and like things like`,
tags: [this.getTagsTemplate("Mango")] //nesting removed
};
this.year++;
return template;
}
Secondly, in JS objects are passed by reference, so you can do this:
method:
addLikes(like) { //removed the extra code
like.tags.push(this.getTagsTemplate("New Apple"));
},
template:
...
<div style="text-align: left; display: flex">
<div> //nesting removed
<div class="tags" v-for="tag in like.tags" :key="tag.id">
{{ tag.name }}
</div>
</div> //passing the reference to the object
<button style="margin-left: 20px" #click="addLikes(like)">
Add Likes
</button>
</div>
Result img

Facing issue while rendering index value of *ngFor directive in Angular 5

I am facing an issue while rendering index of *ngFor directive for a particular use case as follows.
Lets say we have an array of objects as
this.temp = [
{name:'John',age:24,visibility:'visible',
{name:'Kane',age:26,visibility:'hidden',
{name:'Ross',age:28,visibility:'visible',
{name:'Lui',age:21,visibility:'visible'
]
For rendering this in my app.component.html file I have html as follows
<div *ngFor="let user of temp; let i = index">
<div *ngIf="user.visibility === 'visible' ">
<div>{{i+1}}</div>
<div>{{user.name}}</div>
</div>
</div>
So as per the above array example, it renders users
1.John
2.Ross
3.Lui
Now there is a button name 'Change visibility' against each user in my UI, where in it will toggle the visibility state of user from 'hidden' to 'visible' and viceversa.
So clicking on button mentioned against John, it will set its visibility as
hidden but the UI rendered is
2.Ross
3.Lui
My expected output is
1.Ross
2.Lui
How to make the index render properly ?
The use case here is that I cannot modify/alter my this.temp array in terms of length.Basically I need the entire array with only visiblity property changed in it as per user actions.
Please help.
you can filter array first:
<div *ngFor="let user of temp.filter(us => us.visibility === 'visible'); let i = index">
<div>
<div>{{i+1}}</div>
<div>{{user.name}}</div>
</div>
</div>
like this way, you dont analize all array items too, more efficient and desired output.
Cheers!
You can also achieve your required result by using Pipe like this
HTML component
<div *ngFor="let user of temp | visiblefilter ; let i=index">
<span>{{i+1}} {{user.name}}</span> <button name={{user.name}} (click)="onHide($event)">Hide</button>
</div>
PIPE
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'visiblefilter',
pure: false
})
export class VisibleFilterPipe implements PipeTransform {
transform(items: any[]): any {
return items.filter(({visibility}) =>visibility=='visible');
}
}
You can check here with working example stackblitz
use a custom trackby function :
*ngFor="let user of temp; let i = index; trackBy: customTB"
customTB(index, item) {
return index + ' - ' item.name;
}

How to add Bootstrap class to element?

I'm getting this error from the console:
Uncaught DOMException: Failed to execute 'add' on 'DOMTokenList': The
token provided ('si col-md-4') contains HTML space characters, which
are not valid in tokens.
This is my HTML snippet, I want to append the div to the row:
<div id = 'data' class="container">
<div id = 'row1' class = 'row'>
</div>
</div>
This is my javascript code:
var row = document.getElementById('row1');
var div = document.createElement('div');
div.classList.add('si col-md-4');
row.append(div);
I should also note that I'm using a firebase database to get the information I want to append.
To add multiple class, separate class with ,(comma)
var row = document.getElementById('row1');
var div = document.createElement('div');
div.classList.add('si', 'col-md-4');
row.append(div);
<div id = 'data' class="container">
<div id = 'row1' class = 'row'>
test
</div>
</div>
Use , separator if you want to add/remove several classes.
div.classList.add('si','col-md-4');
If you only need to add the class col-md-4,
div.classList.add('col-md-4');
just add multiple classes with space seperated as shown below
div.className='si col-md-4';
Here you go with a solution
$("#row1").append("<div class='si col-md-4'>Test</div>");
.si {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id = 'data' class="container">
<div id = 'row1' class = 'row'>
</div>
</div>
Used jQuery append method.
Well you can use .setAttribute("class","si col-md-4").It will add the whole new class to it.
As you're adding a class so you should also .setAttribute("class","previos-class si col-md-4") do this trick.

Javascript show/hide multiple DIV's

I'm in need of a bit of help. I have a current script that switches div's between being visible and hidden depending on a dropdown selector, it works as it was originally designed absolutely fine.
The problem i have is that i need to modify it to change more than 1 div on the page. Currently i'm using the same ID for the div's but only the first item on the page is updated. Reading over the JS this makes sense, but i can't figure out how to modify it to get the desired result?
Javascript:
var lastDiv = "";
var lastProd = "";
function showDiv(divName, productID) {
if (productID == lastProd) {
$("#"+lastDiv).hide();
$("#"+divName).fadeIn(".visible-div-"+productID);
}
else {
$(".visible-div-"+productID).hide();
$("#"+divName).fadeIn(".visible-div-"+productID);
}
lastProd = productID;
lastDiv = divName;
}
The selector:
<select onchange="showDiv('pxo_'+this.value,2);" name="pre_xo_id">
<option value="3">Blue - £120.00</option>
<option value="4">Red - £120.00</option>
<option value="5">Yellow - £120.00</option>
The DIV's:
<div id="pxo_3" class="visible-div-2" style="display: none;">RED</div>
<div id="pxo_4" class="hidden-div visible-div-2" style="display: none;">BLUE</div>
<div id="pxo_5" class="hidden-div visible-div-2" style="display: block;">YELLOW</div>
<div id="pxo_3" class="visible-div-2" style="display: none;">1 In Stock</div>
<div id="pxo_4" class="hidden-div visible-div-2" style="display: none;">1 In Stock</div>
<div id="pxo_5" class="hidden-div visible-div-2" style="display: none;">0 In Stock</div>
id's must be unique, that's why only the first item is being update. You may put those values to class instead to allow multiple selection.
First you can not use one id for morethan one element.They must be unique.Apply same css class to those elements.
We can use same class instead to allow multiple selection.
IDs are supposed to be used for only a single element on the page. You want to use css selectors.
Thank you for the help all, I have modified the JS to look for both ID and Class as i am unable to change part of the code due to it being protected by ioncube.
This seems to have the desired result:
var lastDiv = "";
var lastProd = "";
function showDiv(divName, productID) {
if (productID == lastProd) {
$("#"+lastDiv).hide();
$("#"+divName).fadeIn(".visible-div-"+productID);
$("."+lastDiv).hide();
$("."+divName).fadeIn(".visible-div-"+productID);
} else {
$(".visible-div-"+productID).hide();
$("#"+divName).fadeIn(".visible-div-"+productID);
$(".visible-div-"+productID).hide();
$("."+divName).fadeIn(".visible-div-"+productID);
}
lastProd = productID;
lastDiv = divName;
}

Categories