How to manipulate many elements inside an ng-repeat? - javascript

I have an array that I want to show through a ng-repeat. But I have inside the div (with the ng-repeat) many other elements which I want to manipulate for each iteration of that ng-repeat. For example:
<div ng-repeat="data in result">
{{data.name}}
<img src="value">
<p class="class">text</p>
</div>
If I want to change the image source with a different source for each element of my array, how can I do this? I can't change anything of result array. I want to change it later, when the user clic in a bottom for example.
Daniel
EDIT:
img tag was just an example. I added other element which could be necessary to change the class. So a different class for each iteration.

To change the image source, use ng-src like:
<div ng-repeat="data in result">
{{data.name}} <img ng-src="{{data.imageUrl}}">
</div>
In this I am assuming you have a property on each data item called imageUrl.
To change the value, just assign a new value to the imageUrl property and angular's two way bindings will do the rest. An example is:
<button ng-click="result[0].imageUrl = 'img/new-image.jpg';">Change Image</button>
Of course, you would want to make sure you have the correct index and that there is at least one element in the result array, but that should do it!
Live Example
To see this in action, check out the following plunker: http://plnkr.co/edit/gYLH7Z4b03lS2gZBHceC?p=preview
EDIT
Based on the edit to the question - if you need to change the class use ng-class. In fact, there is a directive already written for most of the common things that you need to change. Always search the angular documentation first: angularjs.org. If you do need to do something more advanced that isn't already written, read the documentation and create your own directive: https://docs.angularjs.org/guide/directive. Best of luck!

Use ng-src instead of src for string interpolation. See https://docs.angularjs.org/api/ng/directive/ngSrc.

Related

How to add alt text to an image using a data attribute on the parent?

I'm trying to figure out how to add an alt-text attribute to an image by assigning a data attribute to the parent container of that image.
Basically, whatever text I add to data-alt, will be assigned as alt-text on the img element.
How can I write the attribute so that it's applied as alt-text to the image, and not the parent?
What I want to enter in my code editor:
<div class="image-parent" data-alt="hello world">
<img src="path/to/image">
</div>
My desired result:
<div class="image-parent">
<img src="path/to/image" alt="hello world">
</div>
Here's what I've tried, but I'm not understanding how to apply the data attribute to the child element of image.
let imgParentContainers = document.querySelector('.image-parent');
let dataAlt = imgParentContainers.setAttribute('data-alt', '');
<div class="image-parent" data-alt="alt text here">
<img src="https://apkdoll.com/wp-content/uploads/2021/08/HOLLA-Live-Random-Video-Chat-MOD-APK.png">
</div>
You need a few improvements to get to your desired target state:
It's not clear why you'd use setAttribute() to get data from an attribute. As its name implies, it is used solely for setting the value of an attribute. A better attempt would be to use getAttribute(), but in this case, since you're accessing a data-* element, you should probably use HTMLElement.dataset instead.
Unless you anticipate having exactly one element with the class image-parent, you should definitely swap your use of querySelector for querySelectorAll to ensure you get a NodeList of any/all matches instead of just the first one found in the DOM. In this case, you'll also have to use a loop for both (a) all parent containers matching your .image-parent selector, and another for (b) each of the img elements within that container.
Be a bit more specific with your CSS selector in your call to querySelector/querySelectorAll to avoid issues relating to trying to access attributes that don't exist by matching on elements that have the data-alt attribute in the first place.
Your desired end result shows that the data-alt attribute no longer exists on the parent container element; if this is actually desired goal, you don't seem to have attempted to do so in your snippet. Use removeAttribute() for this.
let imgParentContainers = [...document.querySelectorAll('.image-parent[data-alt]')];
imgParentContainers.forEach(parentContainer => {
[...parentContainer.querySelectorAll('img')].forEach(imgElement => {
imgElement.setAttribute('alt', parentContainer.dataset.alt);
});
parentContainer.removeAttribute('data-alt');
});
<div class="image-parent" data-alt="alt text here">
<img src="https://apkdoll.com/wp-content/uploads/2021/08/HOLLA-Live-Random-Video-Chat-MOD-APK.png">
</div>
In the future, you may find it useful to use your preferred search engine to research each individual component of your requirement (appended with your language of choice; JavaScript in this case) to get a better idea of the methods you should be looking to use to achieve your goals. For example, the following Google searches yielded several pre-existing threads on this site alone for each component of the solution:
"read attribute value javascript" yielded How to get the value of an attribute in Javascript
"return all matches queryselector javascript" yields How to get the second match with QuerySelector?
"remove attribute javascript" yields How to remove an attribute from a DOM element using Javascript?

How to retrieve an attr value from an nextAll() retrieved list from one element?

Here's the deal: I need to look up for an element, on a list of others HTMLElements, for the next one that has the class '.wanted-class'. I fire/capture a click event in one of the elements from the same class. I ended up with a solutions that looks like this:
$('#id-element-0000').nextAll('.wanted-class');
This should return a list of all the elements that belongs to this class that are after the one I clicked. Something like this:
<div class=​"wanted-class" id=​"id-element-1111" data-wanted=​"6127">​…​</div>
<div class=​"wanted-class" id=​"id-element-2222" data-wanted=​"6128">​…​</div>
<div class=​"wanted-class" id=​"id-element-3333" data-wanted=​"6129">​…​</div>
<div class=​"wanted-class" id=​"id-element-4444" data-wanted=​"6130">​…​</div>​
But, I only want the first one. I don't need the others. So I came up (AKA: found on google) a solution that was simply:
$('#id-element-0000').nextAll('.wanted-class')[0];
This obviously return this:
<div class=​"wanted-class" id=​"id-element-1111" data-wanted=​"6127">​…​</div>
That solves the first element problem. But, I can't access the data-wanted attribute on the element. Something like:
$('#id-element-0000').nextAll('.wanted-class')[0].attr('data-wanted');
...or...
$('#id-element-0000').nextAll('.wanted-class')[0].data('wanted');
...simply don't work. And I don't seem to be able to put it into a variable too.
QUESTION: does anyone know how to retrieve the data-wanted attribute from the first element from this list?
UPDATE
Obviously, the better way of doing it was to use next intead of nextAll, BUT I have others elements between elements from this same class. So, next function doesn't apply in this case. And, YES... I've tried.
Wrap it with $() to convert it to jQuery object:
$($('#id-element-0000').nextAll('.wanted-class')[0]).attr('data-wanted');
Or simply use
$('#id-element-0000').nextAll('.wanted-class').first().attr('data-wanted');
When you index over jQuery objects, you will get HTMLElement which doesn't have methods that jQuery has.
You are accessing the first element in the jQuery wrapper set. You should convert it to jQuery object again, or get the first item with .eq method which return jQuery object:
$('#id-element-0000').nextAll('.wanted-class').eq(0).attr('data-wanted');
jsFiddle Demo.

Store "templates" of children

I am new to JavaScript so forgive me if the question comes around as dumb.
I know that appendChild() allows me to add a child element to an existing element. However, the problem is that I want to add an element which has an image on the left and a series of text boxes on the right and I need to add it over and over again on button click.
Adding simple elements like p, a , etc can be done by a single call to appendChild(), however for the above scenario, it will be a little messy.
Is there some way that I can define the custom element that I want to append and then just add it with a single call to appendChild()
Are you using jQuery? If it is a really complicated template, you could use .load() to ajax in an template and populate it with whatever you have to. You wouldn't need to dynamically create all of the elements using javascript, only populate it. This would would also allow you to change your template if need be very easily.
It seems you need cloneNode:
target.appendChild(template.cloneNode(true)); // If you want to clone template
// with all its descendants
target.appendChild(template.cloneNode(false)); // If you want to clone template
// without its descendants
I do this quite a bit. My code generally looks like this:
<div class="template" style="display: none;">stuff</div>
then:
$('.template').clone(true).removeClass('template').show().appendTo(someElement);
Since you're not using jQuery, have a look at the clone function here:
http://code.jquery.com/jquery-1.11.0.js
(search for "clone: function" to find it)
You can steal the relevant bits if you can't actually use jQuery itself.

How to create an array of divs with a certain custom data attribute using Javascript

I have a bunch of divs on a page that have a custom data attribute of "data-type"
<div id="155544" data-type="form" data-form-id="155544">
<div data-type="question" data-question-id="119709" data-mandatory="True"></div>
<div data-type="question" data-question-id="119710" data-mandatory="True"></div>
</div>
<div id="155554" data-type="form" data-form-id="155554">
<div data-type="question" data-question-id="119711" data-mandatory="True"></div>
<div data-type="question" data-question-id="119712" data-mandatory="True"></div>
</div>
Thats basically the code, I've just taken out the actual content to avoid confusion.
I want to use Javascript to find out how many divs have the data-type of "form" in order for me to do something with them.
I have found this Hide or show all divs for a certain value of a data attribute Which is similiar to what I want to do, except I'm trying to not use jQuery.
Any solutions?
EDIT: I should also mention that I am trying to not directly use the divs "id" as those are created dynamically
Without using JQuery, you might use querySelectorAll
elementList = document.querySelectorAll('div[data-type="form"]');
Demonstration (prints their number)
You could use querySelectorAll MDN to get a Nodelist, which you can turn into an array (and loose goodies like .namedItem()) if you want:
var divs = document.querySelectorAll('div[data-type="form"]');
var arrayOfDivs = Array.prototype.slice.apply(divs,[0]);

How to get element from template by javascript?

I dont know good method how to get DOM element from template by javascript.
Example template:
<script id = "template" type="text/template">
<div>text1</div>
<div>text2</div>
<div>text3</div>
</script>
For example i want get div with "text2"
There is ways which i know, all of them are bad:
Add "class" to all elements - it breaks semantics (class created for CSS). In big projects you must use very long names for classes, its very inconvenient.
Get element by his number (index) - when adding a new element, you must rewrite old numbers in your code.
I see a couple of options:
If you don't want to use class , you can use a data-* attribute.
Assuming you load the template once and then duplicate its contents as desired, you could put id values on the elements in the template, which you then remove when cloning them and adding them to the document (so you don't end up with the same id on more than one copy of the element, which would be invalid and probably counterproductive).
Maybe you can also create as many templates as you need.
One for each div.
If you need to get each div at a time you must set ids to them ... of course you can also browse the dom inside script element to find the one you're interested in ...
Home this helps
Regards
mimiz

Categories