3

I am trying to figure out how I can clear the <p> elements that are generated from a for loop before the for loop starts.

Essentially. I have a webpage where someone searches something and a list of results are shown. However if I search for something else, the new results get appended instead of clearing the old results first.

Here is the code:

async function parseitglinkquery() {
    var queriedresults = await getitglinkquery();
    console.log(queriedresults);
    const output = document.querySelector('span.ms-font-mitglue');
    output.removeChild("createditginfo"); \\tried to clear the <pre> here and it failed
    for (let i = 0; i < queriedresults.length; i++) {

        let text = "Company: " + JSON.stringify(queriedresults[i]["data"]["attributes"].organization-name) + "<br>"+
        "Name: " + JSON.stringify(queriedresults[i]["data"]["attributes"].name) + "<br>" +
        "Username: " + JSON.stringify(queriedresults[i]["data"]["attributes"].username).replace("\\\\","\\") + "<br>" +
        "Password: " + JSON.stringify(queriedresults[i]["data"]["attributes"].password);
        let pre = document.createElement('p');
        pre.setAttribute("id", "createditginfo")
        pre.innerHTML = text;
        pre.style.cssText += 'font-size:24px;font-weight:bold;';
        output.appendChild(pre);  
    console.log(typeof pre)    
    }
}

I tried to create a try and catch block where it would try to clear the <p> using removeChild() but that didn't seem to work either.

async function parseitglinkquery() {
    var queriedresults = await getitglinkquery();
    console.log(queriedresults);
    const output = document.querySelector('span.ms-font-mitglue');
    try {
        output.removeChild("createditginfo");
    }
    catch(err){
        console.log(err)
    }
    for (let i = 0; i < queriedresults.length; i++) {

        let text = "Company: " + JSON.stringify(queriedresults[i]["data"]["attributes"].organization-name) + "<br>"+
        "Name: " + JSON.stringify(queriedresults[i]["data"]["attributes"].name) + "<br>" +
        "Username: " + JSON.stringify(queriedresults[i]["data"]["attributes"].username).replace("\\\\","\\") + "<br>" +
        "Password: " + JSON.stringify(queriedresults[i]["data"]["attributes"].password);
        let pre = document.createElement('p');
        pre.setAttribute("id", "createditginfo")
        pre.innerHTML = text;
        pre.style.cssText += 'font-size:24px;font-weight:bold;';
        output.appendChild(pre);  
    console.log(typeof pre)    
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 1
    You only have to clear the output-node right before the loop using `output.innerHTML = ''` – Christopher Aug 13 '21 at 23:32
  • This is the answer! If you make an answer for this I will give you credit! Thanks again! –  Aug 13 '21 at 23:44

2 Answers2

2

You only have to clear the output-node right before the loop using the innerHTML-property.

output.innerHTML = '';

There are other ways too, if you want to remove only specific childs. You can make use of Node.childNodes together with a loop. With this, you have the opportunity to remove only specific children.

[...output.childNodes].forEach(childNode => {
  output.removeChild(childNode)
});
// or specific
[...output.childNodes].forEach(childNode => {
   // remove only <div>-nodes
   if (childNode.nodeName == 'DIV') {
     childNode.remove();
   }
});
Christopher
  • 3,124
  • 2
  • 12
  • 29
2

The answer above is correct, but I believe that the original code and the answer can be further improved:

  1. for variables that do not change, use const instead of let - this helps explaining the intention.
  2. there seems to be a bug - if you have an attribute called "organization-name", you cannot access it as a property (...["attributes"].organization-name), but you can use array access instead: ...["attributes"]["organization-name"]. Otherwise, the code end up effectively as ...["attributes"].organization - name
  3. when you have long property paths that are repeated a lot (like queriedresults[i]["data"]["attributes"] in your case), consider assigning them to a local variable. This makes the code more readable and is actually better for performance (because of less array lookups):
    // old code
    let text = "Company: " + JSON.stringify(queriedresults[i]["data"]["attributes"].organization-name) + "<br>"+
               "Name: " + JSON.stringify(queriedresults[i]["data"]["attributes"].name) + "<br>";
    
    // new code
    const attrs = queriedresults[i]["data"]["attributes"];
    let text = "Company: " + JSON.stringify(attrs['organization-name']) + "<br>"+
               "Name: " + JSON.stringify(attrs.name) + "<br>";
    
  4. you are creating several pre's in a loop, this is ok, however the element id must be different! Each id must be unique in the whole page:
    // wrong
    for (let i = 0; i < queriedresults.length; i++) {
       ...
       pre.setAttribute("id", "createditginfo")
       ...
    }
    
    // right/better
    for (let i = 0; i < queriedresults.length; i++) {
       ...
       pre.setAttribute("id", "createditginfo" + i) // "i" for uniqueness
       ...
    }
    
  5. you can use innerText, in which case you do not need to encode the attributes, plus it simplifies the code:
    const pre = document.createElement('p');
    pre.innerText = [
         "Company: " + attrs["organization-name"],
         "Name: " + attrs.name,
         "Username: " + attrs.username, // presumably you don't need to decode "/" anymore :)
         "Password: " + attrs.password
      ].join("\n")     // so we declared a bunch of lines as an array, then we join them with a newline character
    
  6. Finally, regarding the original question, I see three main ways:
    1. simply clearing the contents of the parent with output.innerHtml = ''
    2. iterating over each child and removing it with output.removeChild(childPre)
    3. you can keep references to the generated pre's (eg, store each element in an array) and remove the later with point 2, but this is less automatic but in some cases it might be more efficient if you have a tone of elements at that same level.
Christian
  • 27,509
  • 17
  • 111
  • 155