Search code examples
javascripthtmlarraysjavascript-objects

Javascript AppendChild Issue


UPDATED WITH FULL CODE

I'm trying to dynamically add a div onto some other DIV's stored in an array

The array which contains DIV's is named categoryData which contains an attribute with its category name

The shop-row div's (categoryData) is empty at the beginning.

I've got another array which contains the product object stored in an array called storeCategoryData The product object is in the following format,

{CategoryName:categoryname,StoreObject:store_clearfix} // store_clearfix is another div

I'm trying to add the StoreObject into the DIV categoryData. Unfortunately some objects get added and not the others. I can figure out what i'm doing wrong here. Any help would be much appreciated. Thanks!

I tried doing everything possible. Still no luck :(

 var store_list = document.getElementsByClassName("shop-list")[0];


if(data['stores']!=null && data['stores'] !== typeof undefined){

    var numstores = Object.keys(data["stores"]).length;
    var count = 0;

    while (count < numstores) {

        var categories = data["stores"][count].Categories;
        var catcount = categories.length;
        var c=0;

        while(c<catcount){
            var cat = categories[c];

            if (!(storeCategories.indexOf(cat) > -1)) {

                var category_element = document.createElement("li");
                if(count==0 && c==0){
                    category_element.className="active";
                }
                var clickable = document.createElement("a");
                clickable.href = "#";
                clickable.innerText = cat;
                clickable.setAttribute("category-data", cat);
                storeCategories.push(cat);
                category_element.appendChild(clickable);
                category_list.appendChild(category_element);


                var div = document.createElement("div");
                div.className = "shop-row";
                div.setAttribute("category-name", cat);
                categoryData.push(div);
            }

            c++;
        }

        count++;
    }

    count = 0;

    while (count < numstores) {

        var StoreId = data["stores"][count].StoreId;
        var WebsiteUrl = data["stores"][count].WebsiteUrl;
        var LogoUrl = data["stores"][count].LogoUrl;
        var categories = data["stores"][count].Categories;


        var store_clearfix = document.createElement("div");
        store_clearfix.className = "single-products-catagory clearfix";

        var store_atag =  document.createElement("a");
        store_atag.className = "home-shop";
        store_atag.href = WebsiteUrl;

        var store_img = document.createElement("img");
        store_img.className = "shop-icon";
        store_img.src = LogoUrl;
        store_img.alt = StoreId;

        store_atag.appendChild(store_img);
        store_clearfix.appendChild(store_atag);


        c=0;
        catcount = categories.length;
        while(c<catcount){
            var categoryname = categories[c];
            var i = 0;
            var datacount = categoryData.length;
            while(i<datacount){

                var datarow = categoryData[i];
                if(categoryname==datarow.getAttribute("category-name")) {
                    var storeObj = {CategoryName:categoryname,StoreObject:store_clearfix};
                    storeCategoryData.push(storeObj);
                    break;
                }

                i++;

            }

            c++;
        }


        count++;

    }


    categories_tab.appendChild(category_list);

    i=0;
    for (i = 0; i < categoryData.length; i++) {
        var div = categoryData[i];
        console.log(div);

        var name = div.getAttribute("category-name");

        var c;
        for (c = 0; c < storeCategoryData.length; c++) {
            console.log(storeCategoryData[c].CategoryName);
            if(storeCategoryData[c].CategoryName==name){
                console.log(storeCategoryData[c].StoreObject);
                div.appendChild(storeCategoryData[c].StoreObject);
           }

        }

        console.log("Finished "+name );
        console.log(div);
        store_list.appendChild(div);

    }

}

Example variable data defined as follows

{
"status": "success",
"stores": [
    {
        "StoreId": "randomStore",
        "WebsiteUrl": "https://abcd.com",
        "LogoUrl": "https://abcd.come",
        "Categories": [
            "ALL",
            "MENS",
            "WOMENS"
        ]
    },
    {
        "StoreId": "someStoreId",
        "WebsiteUrl": "https://someurl.com",
        "LogoUrl": "https://someLogo.com",
        "Categories": [
            "MENS"
        ]
    }
  ] 
}

enter image description here


Solution

  • The problem you are facing here is caused by the following behavior:

    The Node.appendChild() method adds a node to the end of the list of children of a specified parent node. If the given child is a reference to an existing node in the document, appendChild() moves it from its current position to the new position (MDN: Node.appendChild())

    What this means is that appendChild will remove the node if already present in the DOM, which is what we are seeing here. This can be easily solved by creating a deep clone of the node first using cloneNode, before appending it to the target div, as follows:

    var clone = storeCategoryData[c].StoreObject.cloneNode(true);
    div.appendChild(clone);
    

    You can also refer to the snippet below for a working example:

    var categories_tab = document.getElementById('category-tab');
    var store_list = document.getElementById('store-list');
    var storeCategories = [];
    var storeCategoryData = [];
    var data = {
      "status": "success",
      "stores": [{
          "StoreId": "randomStore",
          "WebsiteUrl": "https://abcd.com",
          "LogoUrl": "https://abcd.come",
          "Categories": [
            "ALL",
            "MENS",
            "WOMENS"
          ]
        },
        {
          "StoreId": "someStoreId",
          "WebsiteUrl": "https://someurl.com",
          "LogoUrl": "https://someLogo.com",
          "Categories": [
            "MENS"
          ]
        }
      ]
    };
    
    var categoryData = [];
    
    var category_list = document.createElement("ul");
    
    if (data['stores'] != null && data['stores'] !== typeof undefined) {
    
      var numstores = Object.keys(data["stores"]).length;
      var count = 0;
    
      while (count < numstores) {
    
        var categories = data["stores"][count].Categories;
        var catcount = categories.length;
        var c = 0;
    
        while (c < catcount) {
          var cat = categories[c];
    
          if (!(storeCategories.indexOf(cat) > -1)) {
    
            var category_element = document.createElement("li");
            if (count == 0 && c == 0) {
              category_element.className = "active";
            }
            var clickable = document.createElement("a");
            clickable.href = "#";
            clickable.innerText = cat;
            clickable.setAttribute("category-data", cat);
            storeCategories.push(cat);
            category_element.appendChild(clickable);
            category_list.appendChild(category_element);
    
    
            var div = document.createElement("div");
            div.className = "shop-row";
            div.setAttribute("category-name", cat);
            categoryData.push(div);
          }
    
          c++;
        }
    
        count++;
      }
    
      count = 0;
    
      while (count < numstores) {
    
        var StoreId = data["stores"][count].StoreId;
        var WebsiteUrl = data["stores"][count].WebsiteUrl;
        var LogoUrl = data["stores"][count].LogoUrl;
        var categories = data["stores"][count].Categories;
    
    
        var store_clearfix = document.createElement("div");
        store_clearfix.className = "single-products-catagory clearfix";
    
        var store_atag = document.createElement("a");
        store_atag.className = "home-shop";
        store_atag.href = WebsiteUrl;
    
        var p = document.createElement("p");
        p.className = "shop-icon";
        var t = document.createTextNode(LogoUrl);
        p.appendChild(t)
    
        store_atag.appendChild(p);
        store_clearfix.appendChild(store_atag);
    
    
        c = 0;
        catcount = categories.length;
        while (c < catcount) {
          var categoryname = categories[c];
          var i = 0;
          var datacount = categoryData.length;
          while (i < datacount) {
    
            var datarow = categoryData[i];
            if (categoryname == datarow.getAttribute("category-name")) {
              var storeObj = {
                CategoryName: categoryname,
                StoreObject: store_clearfix
              };
              storeCategoryData.push(storeObj);
              break;
            }
    
            i++;
    
          }
    
          c++;
        }
    
    
        count++;
    
      }
    
    
      categories_tab.appendChild(category_list);
    
      i = 0;
      for (i = 0; i < categoryData.length; i++) {
        var div = categoryData[i];
        console.log(div);
    
        var name = div.getAttribute("category-name");
    
        var c;
        for (c = 0; c < storeCategoryData.length; c++) {
          console.log(storeCategoryData[c].CategoryName);
          if (storeCategoryData[c].CategoryName == name) {
            console.log(storeCategoryData[c].StoreObject);
            var clone = storeCategoryData[c].StoreObject.cloneNode(true);
            div.appendChild(clone);
          }
    
        }
    
        console.log("Finished " + name);
        console.log(div);
        store_list.appendChild(div);
    
      }
    
    }
    <div id="category-tab" style="min-height: 20px; border: 1px solid; padding: 10px"></div>
    <div id="store-list" style="min-height: 20px; border: 1px solid green; padding: 10px; margin-top: 30px"></div>