Jquery like DOM selection in Angular5 - javascript

Let's suppose we have Angular component whose content is provided as follows:
<component-A>
<span class = "parent">
<div class = "toBeSelected"> DemoContent</div>
</span>
<div class = "toBeSelected"> DemoContent2</div>
</component-A>
In jQuery if I need to select element by selector toBeSelected
$('.toBeSelected').click(function(){
var clickedSpanTxt = $(this).html();
console.log(clickedTxt);
});
Is there any library exists which helps in selecting nested DOM elements from the component.
As #ContentChildren of Angular5 only selects direct child of the component by selector i.e. I can only select span with the class parent or only one div with class toBeSelected.
Is there any way to select both div with class toBeSelected.

You can use the DOM APIs. As document is directly available in angular component (.ts file). So you can use
let elSelected = document.querySelectorAll(".toBeSelected");
that will return the array of dom elements.

Use the same callback function on both elements, or make toBeSelected another component with a callback function enclosed in it.
Read this

Related

How do you add an element to a class (through JavaScript)?

Suppose that I want to add a newly created paragraph (using document.createElement("p")) into an existing div (with class name "container") in one of my html files. Is there a way to do this by calling some methods?
Since there's a getElementById() method, I figured I would use a getElementByClassName() method too, but that doesn't exist; what exists is getElementsByClassName() instead. One way I can get around this is to just change my div to have an id rather than a class name, and use the getElementById() to add the paragraph into the div, but I wanted to know if there was some method that I could call that would help me retrieve a class element (rather than the elements within the class itself).
I've tried looking for this online, but what I've found are answers to "how to add class names to elements" instead, which is not what I want to know.
For one element, this will chose first in DOM order:
var p = document.createElement("p");
p.innerHTML = "p element";
document.querySelector(".container").appendChild(p);
<div class="container">container</div>
For all elements with chosen class:
[...document.querySelectorAll('.container')].forEach(el => {
var p = document.createElement("p");
p.innerHTML = "p element";
el.appendChild(p);
})
<div class="container">container</div>
<div class="container">container2</div>
HTML DOM elements' IDs have to be unique within a document - and so asking for an element by Id will return you just one element (or null if there isn't a matching element).
However a class name can be applied to multiple elements, so you would expect to get zero one or more elements when searching by class, hence the getElementsByClassName returns a collection.
So if you have a list of elements with the class name container, and you know your document (hopefully) only contains one element with that name, you can pick the first element returned by the getElementsByClassName - e.g. getElementsByClassName('container')[0]
Note - getElementsByClassName returns all elements to which the class has been directly applied, for the children of the element on which it is being called. I've interpreted your query as relating to the whole document in the context of your original question.

How can we append childnodes to ng-content without rerendering the Angular Elements?

The child nodes which Iam appending are not properly positioned inside the ng-content area of the custom element I created using Angular element.
I tried to reporduce my issue in this Stackblitz
Current solution
It will work if I add the child nodes to the created custom element instance before adding to dom .
Expected Solution
Is there any way I can easily add a childnode to my custom angular
element using javascript(appendChild) without rerendering the whole
component again.
Thanks.
You could use getElementsByClassName:
onAddChild2(e: string) {
let div = document.createElement("div");
div.innerHTML = e;
const eHost = document.getElementsByClassName('container')[0];
eHost.appendChild(div);
}
Check the Stackblitz I forked from you code: https://stackblitz.com/edit/angular-elements-exp-v3r4b3
This is not the Angular way. You should not be manipulating the DOM directly like this. You should be binding an array to your template.
children = ['New Child'];
onAddChild() {
this.children.push('New child');
}
and in the template
<div *ngFor="let child of children">{{child}}</div>

Select node from children by attribute

I have an interface that switches between displaying different div elements. When it switches which element it displays, I need to access a specific child node of that div element, with each div element having their children arranged differently.
The childNodes and children property both return an object that can only select children with item(index) which is annoying to use as the relevant child element's index is different in each div. For Protractor, I used the webmanager.by(selector) which was able to search with other parameters than index. Is there something similar I can use to select the child node with data-relevant="true". I am also unsure if that attribute is the best way to specify in the HTML which child node is relevant.
This is an Angular application if that helps.
If you want to select the child node with data-relevant="true" from some parent element, you could use the selector method
element.querySelector()
That would return the first matching element...
in your specific case it could be something like
parent-element.querySelector( "[data-relevant='true']" );
or if you want to select all paragraphs p with the data-relevant attribute value true within the parent div: parentDiv.querySelectorAll( "p[data-relevant='true']" );
You can find some examples on
http://www.w3.org/TR/selectors-api/#processing-selectors
An alternative would be to use a special class to identify which child node is relevant...
you could get this element/or many elements with getElementsByClassName(someClassName)
Code Sample With .querySelectorAll() method:
<script type="text/javascript">
window.addEventListener("load", init, false);
function init(){
var parentDiv = document.getElementById("divWithChildren");
var relevantChildren = parentDiv.querySelectorAll( "[data-relevant='true']" );
alert (relevantChildren[2].id); // this will give the id of the 3rd child element with data-relevant='true'
}
</script>

count elements of a class within another class

What is the best way to count elements of a particular class within another element?
I have the class of the parent element, but there are other elements with that class. So if for example I have an element that i get to like this:
$(document).on('click', '.countButton', function(){
var parent = $(this).parents('parentDiv');
});
How can I put that element into a selector to count it like this:
$('.parentDiv > .childDivs').length;
Is there someway to convert an element into a selector, or something that points to that element? If that makes sense..
Thanks!
So after var parent = $(this).parents('parentDiv'); you have the element you want and you just want its children with a certain class? If so
parent.children('.childDivs').length;
For direct descendants or:
parent.find('.childDivs').length;
To find elements with the 'childDivs' class at any depth with parent
Yes, you can use the parent element as context for the search:
$('.childDivs', parent).length
Which is the same as:
parent.find('.childDivs').length
Could you perhaps use:
document.querySelectorAll('.parentDiv > .childDivs').length?

Accessing elements inside dynamically created divs with HTML/Javascript

I'm quite new to javascript and JQuery programming. Usually, to access elements I give them an id, so I can get them like $("#"+id).blabla().
But now I need to dynamically create a div, and access elements inside it.
Something like
<div id="automaticallyGeneratedId">
<div ???></div> <!-- first div -->
<div ???></div> <!-- second div -->
</div>
What are the best practices to access and identify each of the inner divs?
I generate another id for them?
Or what?
I don't have the theory of selectors fully clear.
edit: modified the question from identifying a single inner div to identifying divs amongs many of them
You can maintain a pattern when you're generating id. For example:
if you always generate id like: myid1, myid2,myid3...
<div id="myid1">
<div></div>
</div>
<div id="myid2">
<div></div>
</div>
......
then you can try:
$('div[id^=myid]').find('div').foo();
OR
$('div[id^=myid] div').foo();
Here, ^= is start with selector, so div[id^=myid] will select div whose id start with myid.
You can also use Contain word selector which is ~= and use like $('div[id~=myid]'). This will select div with id contains word myid.
Instead of id if you want to use other attribute eg. name then change selector like:
$('div[name^=myid]') or $('div[name~=myid]').
It's usually a good practice that if you already have a reference to that outer div to just search from there using find.
You can give it an id, or if you want to use a more general approach you can use classes.
<div class="subdiv">...
$('#automaticallyGeneratedId').find('div.subdiv')
Usually, when you create them, you can assign event handlers and the likes straight on them. Like this:
var div = $( '<div></div>' );
div.on( 'click', function() {
// Do something when the generated div is clicked
});
// Then, add it to the DOM
$( 'body' ).append( div );
You don't need to bother selecting them with ID or classes, they're already available in your code.
Another way is to use event bubbling to handle newly created elements of the same class. A good link about this is this one: http://beneverard.co.uk/blog/understanding-event-delegation/
Many ways you can create an element and give him an Id or Class, or use the DOM to access it..
$("html").prepend('<div id="foo"></div>');
$("#foo").doSomething();
another way
$("#automaticallyGeneratedId").find("div").doSomething();
To access the div in the element with the id:
$("#automaticallyGeneratedId div").whatever
If you cache the divs you could use something like:
var myDiv1Child = $('div', myDiv1);
Create a delegated listener and within the listener you can find the element by doing this
//If a div inside the parent is clicked then execute the function within
$('.PARENT_CLASS').click("div", function(){
//This variable holds all the elements within the div
var rows = document.querySelector('.PARENT_CLASS').getElementsByTagName('div');
for (i = 0; i < rows.length; i++) {
rows[i].onclick = function() {
console.log(this); //The element you wish to manipulate
}
}
});

Categories

Resources