Search code examples
javascriptfor-loopinputappendchild

How to append a span tag and give each id a new name


I have 3 inputs that are nestled inside a span tag (I'm using span and not li because I have many li's in my code). I have a javascript function that appends each span tag (which includes the 3 inputs). I need each input to have a specific id name. Not sure how to do this, I'm learning javascript right now so forgive me for I'm a noob.

In my function I have the appendchild working for the span tag. At the bottom of the code I have a for loop that I wrote to append an ul/li and that name works. But I can't get that same functionality to work for the span tags.

How can I append child and each time I appendchild that the inputs get a new id name?

Here is my code so far:

            function budgetList(){

            var elmnt = document.getElementsByTagName("SPAN")[0];
            var cln = elmnt.cloneNode(true);
            var budgetListing = document.getElementById("budget-listing");
            var append = budgetListing.appendChild(cln);

            var expenseName = document.getElementById('expenseName');
            var expectedExpense = document.getElementById('expectedExpense');
            var actualExpense = document.getElementById('actualExpense');


            var ul = document.createElement("ul");
            document.body.appendChild(li);

            for(var i = 0; i <= 0; i++){
                var li = document.createElement("li");
                li.className = "budget-list" + i;

                var a = document.createElement("a");
                a.innerHTML = "<input type='text'>";
                // a.innerHTML = "Subfile " + i;

                var att = document.createAttribute("class");
                att.value = "budgeting" + i;


                li.appendChild(a);
                ul.appendChild(li);

            }

        }

Here is the html

        <button onclick="budgetList()">Add New Row</button>
        <input type="button" value="save" onclick="save()" />
        <ul id="budget-listing">
            <span>
                <input type="text" id="expenseName">
                <input type="text" id="expectedExpense">
                <input type="text" id="actualExpense">
            </span>        
        </ul>

Solution

  • A few things...

    1) <ul> stands for Unordered List and <ul> elements expect their children to be <li> elements (which you can remember as List Item). So, while some browsers may be forgiving of you appending spans to your <ul> tag, it's not considered good practice. And is technically a violation of the standard

    2) Your loop will only run exactly once. You'll see it's starting with variable i initialized at 0 and will only run as long as i<=0 which will only ever be true on the first iteration because afterwards you increment (i++) which means the second time through i will equal 1 and 1 is NOT less than or equal to 0. So, in this case there's no need to use a loop at all.

    3) Your code is a little disjointed from what you requested and what the page context is suggesting. It appears to me, when the user clicks the button you want to duplicate the span with 3 inputs. If this is indeed the case, then I offer the following solution...

    function budgetList(){
            // You get the span that will serve as a template, good
            var elmnt = document.getElementsByTagName("SPAN")[0];
    
            // you clone it, good
            var cln = elmnt.cloneNode(true);
    
            //next we want to modify the IDs of the child spans.
            // A good way to do this is to use a unique number that will change with every step
            // There a few ways to get a unique number each time
            // I propose taking the number of span groups
            var budgetListing = document.getElementById("budget-listing");
            var uniqueNumber = budgetListing.childNodes.length;
    
            // Now we update all the ids using the unique number
            cln.getElementsByTagName('INPUT')[0].setAttribute('id', "expenseName_"+uniqueNumber);
            cln.getElementsByTagName('INPUT')[1].setAttribute('id', "expectedExpense_"+uniqueNumber);
            cln.getElementsByTagName('INPUT')[2].setAttribute('id', "actualExpense_"+uniqueNumber);
    
            // and write our new span group into the container
            budgetListing.appendChild(cln);
    }
    

    Let me know if I made any incorrect assumptions or if this is close to what you're requesting. JavaScript and its interaction with HTML can be confusing at first, but stick with it!

    EDIT: Didn't realize getElementById wasn't a function... Replaced with getElementsByTagName