11

I'm looping through all anchor tag in an HTML with a class (.add-to-cart) to change text content to shop now, using map() but i am getting an error that says .map is not a function.

<!--HTML CODE -->
 <div class="four columns">
        <div class="card">
                <a href="#" class="u-full-width button-primary button input add-to-cart" data-id="5">Add to Cart</a>
        </div>
</div> <!--.card-->
<div class="four columns">
        <div class="card">
                <a href="#" class="u-full-width button-primary button input add-to-cart" data-id="5">Add to Cart</a>
        </div>
</div> <!--.card-->
<div class="four columns">
        <div class="card">
                <a href="#" class="u-full-width button-primary button input add-to-cart" data-id="5">Add to Cart</a>
        </div>
</div> <!--.card-->


//JAVASCRIPT CODE
const addCartBtns = document.querySelectorAll('.add-to-cart');


addCartBtns.map(function(cartBtn){
  console.log(cartBtn.textContent="shop now");
});

I expect the output to change text content of anchor tags to "shop now".

Samuel Tengan
  • 315
  • 3
  • 10
  • If you're not going to use the return value of `.map()` than you shouldn't be using `.map()`. In your case you should be using `.forEach()` - and with a modern browser this will already be available on the [`NodeList`](https://developer.mozilla.org/en-US/docs/Web/API/NodeList/) – Andreas Apr 07 '19 at 16:43

3 Answers3

23

document.querySelectorAll returns a NodeList which should be converted to real Array before using map()

The Document method querySelectorAll() returns a static (not live) NodeList representing a list of the document's elements that match the specified group of selectors

You can use Spread Operator

const addCartBtns = [...document.querySelectorAll('.add-to-cart')]

Or you can can use Array.from

const addCartBtns = Array.from(document.querySelectorAll('.add-to-cart'))

Notice that you are using map(). map() is used when you want to create a new array bases on the values of existing array of same length. Here you are modifying the array. So you can use forEach

addCartBtns.forEach(function(cartBtn){
  console.log(cartBtn.textContent="shop now");
});

Note:forEach will work fine if NodeList is not converted to array.

Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
1

Here, you don't actually need map, forEach will do, and NodeList has a forEach. Therefore:

addCartBtns.forEach(function(cartBtn) {
  console.log(cartBtn.textContent="shop now");
});
mbojko
  • 13,503
  • 1
  • 16
  • 26
1

You cannot use map simply because the output from querySelectorAll is a NodeList object, not Array. If you want to loop every item in the NodeList, you should use forEach instead.

Take a look at the NodeList API documentation:
https://developer.mozilla.org/en-US/docs/Web/API/NodeList


However you can quickly convert NodeList object to Array
Fastest way to convert JavaScript NodeList to Array?

[...addCartBtns]

Array.prototype.slice.call(addCartBtns);

Array.from(addCartBtns)
Damian Bartosik
  • 498
  • 6
  • 24