Search code examples
javascripthtmlformstemplatetags

Trying to use a template tag to extend forms using javascript


What I am trying to do is add in an "add item button" to this HTML page that will take the template and generate it above the submit button.

However, I am getting an error on line newFields.id = ''; AFTER I create an additional object. So it runs once then breaks. The error is: Uncaught TypeError: Cannot set property 'id' of null at moreProducts (Survey.html:26) at HTMLInputElement.onclick (Survey.html:113) This is the first time I am using JavaScript and hope it is a simple mistake.

Here is my Code Survey.HTML

<!--  NOTE: Please add the following <META> element to your page <HEAD>.      -->
<!--  If necessary, please modify the charset parameter to specify the        -->
<!--  character set of your HTML page.                                        -->
<!--  ----------------------------------------------------------------------  -->

<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8">

<!--  ----------------------------------------------------------------------  -->
<!--  NOTE: Please add the following <FORM> element to your page.             -->
<!--  ----------------------------------------------------------------------  -->

<form action="https://webto.WebToLead?encoding=UTF-8" method="POST">


<script language="javascript">
    var counter = 0;

function moreProducts()
{
    counter++;
    var template = document.getElementsByTagName("template")[0];
    newFields = template.content.querySelector("div");
    newFields.id = '';
    newFields.style.display = 'block';
    var newField = newFields.childNodes;
    for( var i=0; i<newField.length; i++)
    {
        var theName = newField[i].name
        if(theName)
        {
            newField[i].name = theName + counter;
        }
    }
    var insertHere = document.getElementById('submit');
    insertHere.parentNode.insertBefore(newFields,insertHere);
}
</script>

<!--  ----------------------------------------------------------------------  -->
<!--  NOTE: These fields are optional debugging elements. Please uncomment    -->
<!--  these lines if you wish to test in debug mode.                          -->
 <input type="hidden" name="debug" value=1>                             
<!--  ----------------------------------------------------------------------  -->

<label for="first_name">First Name</label><input  id="first_name" maxlength="40" name="first_name" size="20" type="text" /><br>

<label for="last_name">Last Name</label><input  id="last_name" maxlength="80" name="last_name" size="20" type="text" /><br>

<label for="email">Email</label><input  id="email" maxlength="80" name="email" size="20" type="text" /><br>

<label for="phone">Phone</label><input  id="phone" maxlength="40" name="phone" size="20" type="text" /><br>

<label for="company">Company</label><input  id="company" maxlength="40" name="company" size="20" type="text" /><br>

<label for="url">Website</label><input  id="url" maxlength="80" name="url" size="20" type="text" /><br>

<label for="street">Street</label><textarea name="street"></textarea><br>

<label for="city">City</label><input  id="city" maxlength="40" name="city" size="20" type="text" /><br>

<label for="state">State/Province</label><input  id="state" maxlength="20" name="state" size="20" type="text" /><br>

<label for="zip">Zip</label><input  id="zip" maxlength="20" name="zip" size="20" type="text" /><br>

Project Name:<input  id="00N3a00000COzOT" maxlength="50" name="00N3a00000COzOT" size="20" type="text" /><br>

<template>
    <div>
        <input type="button" value="Remove Item" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" /><br /><br />

        Product Description:<textarea  id="00N3a00000COzOY" name="00N3a00000COzOY" rows="15" type="text" wrap="soft"></textarea><br>

        Product Name:<input  id="00N3a00000CP0vo" maxlength="25" name="00N3a00000CP0vo" size="20" type="text" /><br>

        Product Weight:<input  id="00N3a00000COzOd" name="00N3a00000COzOd" size="20" type="text" /><br>

        Product Width:<input  id="00N3a00000COzOi" name="00N3a00000COzOi" size="20" type="text" /><br>

        Product Length:<input  id="00N3a00000COzOn" name="00N3a00000COzOn" size="20" type="text" /><br>

        Product Height:<input  id="00N3a00000COzOs" name="00N3a00000COzOs" size="20" type="text" /><br>

    </div>
</template>

<div id= "First Product">
    <input type="button" value="Remove Item" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" /><br /><br />

    Product Description:<textarea  id="00N3a00000COzOY" name="00N3a00000COzOY" rows="15" type="text" wrap="soft"></textarea><br>

    Product Name:<input  id="00N3a00000CP0vo" maxlength="25" name="00N3a00000CP0vo" size="20" type="text" /><br>

    Product Weight:<input  id="00N3a00000COzOd" name="00N3a00000COzOd" size="20" type="text" /><br>

    Product Width:<input  id="00N3a00000COzOi" name="00N3a00000COzOi" size="20" type="text" /><br>

    Product Length:<input  id="00N3a00000COzOn" name="00N3a00000COzOn" size="20" type="text" /><br>

    Product Height:<input  id="00N3a00000COzOs" name="00N3a00000COzOs" size="20" type="text" /><br>

</div>





<input id="submit" type="submit" name="submit">

<input type="button" id="moreFields" value="Add Another Item" onclick="moreProducts()"/>

</form>



Solution

  • Reason: you are directly working on DOM instead of creating clone of it in template. so it get the original DOM, insert it into another div and next time it won't find the DOM.

    Solution: Change JS as below,

        function moreProducts()
    {
        counter++;
        var template = document.getElementsByTagName("template")[0].cloneNode(true); // THIS change will create clone of DOM instead of working on it directly
        newFields = template.content.querySelector("div");
        newFields.id = '';
        newFields.style.display = 'block';
        var newField = newFields.childNodes;
        for( var i=0; i<newField.length; i++)
        {
            var theName = newField[i].name
            if(theName)
            {
                newField[i].name = theName + counter;
            }
        }
        var insertHere = document.getElementById('submit');
        insertHere.parentNode.insertBefore(newFields,insertHere);
    }