16

I have an HTMLCollection Object which i can use to manipulate the content of the HTMLCollection. I would like to know the way out to add a div element to the first, last or to any specific index of the HTMLCollection. Please suggest something. Here nDivs is the HTML Collection.

    var Div = document.createElement('div');
    for(i=0; i<9; i++){
        Div.appendChild(nDivs[0].children[0]);
    }
    Div.id = nDivs[0].id;
    nDivs[0].parentNode.removeChild(nDivs[0]);

    nDivs.appendChild(Div); //this is creating problem..need an alternative to this
    document.getElementById("ABC").appendChild(nDivs[nDivs.length - 1]);
Ruchir
  • 313
  • 1
  • 3
  • 9
  • I have tried a lot many approaches...converting the collection into an array and then proceeding but that doesn't serve my purpose. I am able to remove an element from that collection but adding an element is not happening. – Ruchir Jan 13 '12 at 19:48
  • Maybe copy some code here that sets up your HTMLCollection, and shows exactly what you want – cambraca Jan 13 '12 at 19:49
  • I suggest including some code in your question, and pointing out specifically what your difficulty is. – calebds Jan 13 '12 at 19:49

2 Answers2

26

According to the MDN docs

HTMLCollection is an interface representing a generic collection of elements (in document order) and offers methods and properties for traversing the list.

Because its an interface, you're restricted to interacting with an HTMLCollection via its methods. There are no methods there to modify the object, only to read it. You'll have to manipulate the DOM some other way.

Here are some suggestions using pure JS, but I highly recommend jQuery for such tasks. Assume we're working with a new element newDiv and the HTMLCollection document.forms:

insert before forms[1]:

forms[1].parentNode.insertBefore(newDiv, forms[1]);

insert after forms[1]:

// there is no insertAfter() so use the next sibling as reference element
forms[1].parentNode.insertBefore(newDiv, forms[1].nextSibling);

replace forms[1]:

forms[1].parentNode.replaceChild(newDiv, forms[1]);

Documentation and examples for insertBefore(), replaceChild(), nextSibling, and parentNode.

calebds
  • 25,670
  • 9
  • 46
  • 74
  • if `forms` is the parent node already, why do you do `forms[1].parentNode.insertBefore(...)` and not simply `forms.insertBefore(...)`? – BitTickler Jul 01 '23 at 10:28
0

You need to insert your new Elements in the DOM directly. You cannot manipulate a read-only HTMLCollection directly. But don't worry, your HTMLCollection (stored in a variable) will update accordingly:

// DOM helper functions:
const el = (sel, par) => (par || document).querySelector(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);


// Cache a reference to the wrapper parent Element 
const elParent = el("#parent-a");

// Cache a live HTMLCollection:
const collItems = elParent.children;

// Insert new elements in the DOM:
elParent.prepend(elNew("div", {textContent: "Item First (New)"}));
elParent.append(elNew("div", {textContent: "Item Last (New)"}));

// Check if the collection is live:
console.log(collItems.length); // 5
<div id="parent-a">
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
</div>

as you can see above (contrary to if you used i.e: const collItems = elParent.querySelectorAll(".item");) the live HTMLCollection reports that is has 5 children in total.

Also, you can see how to append and prepend an item as first or last.
To answer your other question:

"how to insert at a specific index"

you can use:

// DOM helper functions:
const el = (sel, par) => (par || document).querySelector(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
const insertAtIndex = (idx, parent, ...els) => {
  els = els.flat();
  const ch = parent.children;
  if (idx >= ch.length) parent.append(...els);
  else ch[Math.max(idx, 0)].before(...els);
};

// Cache a reference to the wrapper parent Element 
const elParent = el("#parent-a");
// Cache a live HTMLCollection:
const collItems = elParent.children;
// Insert element/s at index
insertAtIndex(
  2,
  elParent,
  elNew("div", {textContent: "NEW item 1"}),
  elNew("div", {textContent: "NEW item 2"}),
);

console.log(collItems.length); // 4
<div id="parent-a">
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
</div>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313