Appending html create inputs with different order










2















I have a html with three inputs like:



enter image description here



Html:



<div class="form-group" id="item-list0">
<label>Role Name</label>
<input asp-for="RoleClaimList[0].Role.Name" class="form-control roles" />
<div id="claim-list0">
<label>Claim Type</label>
<input asp-for="RoleClaimList[0].ClaimList[0].Type" class="form-control claimType" />
<label>Claim Value</label>
<input asp-for="RoleClaimList[0].ClaimList[0].Value" class="form-control claimValue" />
</div>
<a href="#" id="addClaim">Add another claim</a>
</div>

<a href="#" id="add">Add another role</a>


As you can see I have two actions "Add another role" and "Add another claim"



If I press add another claim it just replicate Claim Type and Claim Value inputs



If I press "Add another role" it add all inputs again



I achieve that with Jquery as:



<script>
$(function ()
var roleIndex = 0;
var claimIndex = 0;
$("#add").click(function (e)
e.preventDefault();
roleIndex = roleIndex + 1;
claimIndex = 0;
var n = '<div id="item-list' + roleIndex +'"><label>Role Name</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].Role.Name" /></div>'
var m = '<div id="claim-list' + roleIndex+'"><label>Claim Type</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Type" />'
var c = '<label>Claim Value</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Value" /> </div>'
$("#item-list" + (roleIndex - 1) + "").append(n);
$("#claim-list" + (roleIndex - 1) + "").append(m);
$("#claim-list" + (roleIndex - 1) + "").append(c);
);

$("#addClaim").click(function (e)
e.preventDefault();
claimIndex = claimIndex + 1;
var m = '<div id="claim-list' + claimIndex + '"><label>Claim Type</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Type" />'
var c = '<label>Claim Value</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Value" /> </div>'
$("#claim-list" + (claimIndex - 1) + "").append(m);
$("#claim-list" + (claimIndex - 1) + "").append(c);
);

);
</script>


If I add claim it works correctly. Problem start when I add a new role. It should replicate first tree inputs in same order of first one, but it is creating Claim Type first then Claim Value and finally Role Name as this picture:



enter image description here



What I'm doing wrong there? Regards










share|improve this question






















  • Consider how your logic is using both roleIndex and claimIndex to determine which #claim-list to append to. You're going to be duplicating claim-list ids

    – Taplar
    Nov 12 '18 at 23:33
















2















I have a html with three inputs like:



enter image description here



Html:



<div class="form-group" id="item-list0">
<label>Role Name</label>
<input asp-for="RoleClaimList[0].Role.Name" class="form-control roles" />
<div id="claim-list0">
<label>Claim Type</label>
<input asp-for="RoleClaimList[0].ClaimList[0].Type" class="form-control claimType" />
<label>Claim Value</label>
<input asp-for="RoleClaimList[0].ClaimList[0].Value" class="form-control claimValue" />
</div>
<a href="#" id="addClaim">Add another claim</a>
</div>

<a href="#" id="add">Add another role</a>


As you can see I have two actions "Add another role" and "Add another claim"



If I press add another claim it just replicate Claim Type and Claim Value inputs



If I press "Add another role" it add all inputs again



I achieve that with Jquery as:



<script>
$(function ()
var roleIndex = 0;
var claimIndex = 0;
$("#add").click(function (e)
e.preventDefault();
roleIndex = roleIndex + 1;
claimIndex = 0;
var n = '<div id="item-list' + roleIndex +'"><label>Role Name</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].Role.Name" /></div>'
var m = '<div id="claim-list' + roleIndex+'"><label>Claim Type</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Type" />'
var c = '<label>Claim Value</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Value" /> </div>'
$("#item-list" + (roleIndex - 1) + "").append(n);
$("#claim-list" + (roleIndex - 1) + "").append(m);
$("#claim-list" + (roleIndex - 1) + "").append(c);
);

$("#addClaim").click(function (e)
e.preventDefault();
claimIndex = claimIndex + 1;
var m = '<div id="claim-list' + claimIndex + '"><label>Claim Type</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Type" />'
var c = '<label>Claim Value</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Value" /> </div>'
$("#claim-list" + (claimIndex - 1) + "").append(m);
$("#claim-list" + (claimIndex - 1) + "").append(c);
);

);
</script>


If I add claim it works correctly. Problem start when I add a new role. It should replicate first tree inputs in same order of first one, but it is creating Claim Type first then Claim Value and finally Role Name as this picture:



enter image description here



What I'm doing wrong there? Regards










share|improve this question






















  • Consider how your logic is using both roleIndex and claimIndex to determine which #claim-list to append to. You're going to be duplicating claim-list ids

    – Taplar
    Nov 12 '18 at 23:33














2












2








2








I have a html with three inputs like:



enter image description here



Html:



<div class="form-group" id="item-list0">
<label>Role Name</label>
<input asp-for="RoleClaimList[0].Role.Name" class="form-control roles" />
<div id="claim-list0">
<label>Claim Type</label>
<input asp-for="RoleClaimList[0].ClaimList[0].Type" class="form-control claimType" />
<label>Claim Value</label>
<input asp-for="RoleClaimList[0].ClaimList[0].Value" class="form-control claimValue" />
</div>
<a href="#" id="addClaim">Add another claim</a>
</div>

<a href="#" id="add">Add another role</a>


As you can see I have two actions "Add another role" and "Add another claim"



If I press add another claim it just replicate Claim Type and Claim Value inputs



If I press "Add another role" it add all inputs again



I achieve that with Jquery as:



<script>
$(function ()
var roleIndex = 0;
var claimIndex = 0;
$("#add").click(function (e)
e.preventDefault();
roleIndex = roleIndex + 1;
claimIndex = 0;
var n = '<div id="item-list' + roleIndex +'"><label>Role Name</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].Role.Name" /></div>'
var m = '<div id="claim-list' + roleIndex+'"><label>Claim Type</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Type" />'
var c = '<label>Claim Value</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Value" /> </div>'
$("#item-list" + (roleIndex - 1) + "").append(n);
$("#claim-list" + (roleIndex - 1) + "").append(m);
$("#claim-list" + (roleIndex - 1) + "").append(c);
);

$("#addClaim").click(function (e)
e.preventDefault();
claimIndex = claimIndex + 1;
var m = '<div id="claim-list' + claimIndex + '"><label>Claim Type</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Type" />'
var c = '<label>Claim Value</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Value" /> </div>'
$("#claim-list" + (claimIndex - 1) + "").append(m);
$("#claim-list" + (claimIndex - 1) + "").append(c);
);

);
</script>


If I add claim it works correctly. Problem start when I add a new role. It should replicate first tree inputs in same order of first one, but it is creating Claim Type first then Claim Value and finally Role Name as this picture:



enter image description here



What I'm doing wrong there? Regards










share|improve this question














I have a html with three inputs like:



enter image description here



Html:



<div class="form-group" id="item-list0">
<label>Role Name</label>
<input asp-for="RoleClaimList[0].Role.Name" class="form-control roles" />
<div id="claim-list0">
<label>Claim Type</label>
<input asp-for="RoleClaimList[0].ClaimList[0].Type" class="form-control claimType" />
<label>Claim Value</label>
<input asp-for="RoleClaimList[0].ClaimList[0].Value" class="form-control claimValue" />
</div>
<a href="#" id="addClaim">Add another claim</a>
</div>

<a href="#" id="add">Add another role</a>


As you can see I have two actions "Add another role" and "Add another claim"



If I press add another claim it just replicate Claim Type and Claim Value inputs



If I press "Add another role" it add all inputs again



I achieve that with Jquery as:



<script>
$(function ()
var roleIndex = 0;
var claimIndex = 0;
$("#add").click(function (e)
e.preventDefault();
roleIndex = roleIndex + 1;
claimIndex = 0;
var n = '<div id="item-list' + roleIndex +'"><label>Role Name</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].Role.Name" /></div>'
var m = '<div id="claim-list' + roleIndex+'"><label>Claim Type</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Type" />'
var c = '<label>Claim Value</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Value" /> </div>'
$("#item-list" + (roleIndex - 1) + "").append(n);
$("#claim-list" + (roleIndex - 1) + "").append(m);
$("#claim-list" + (roleIndex - 1) + "").append(c);
);

$("#addClaim").click(function (e)
e.preventDefault();
claimIndex = claimIndex + 1;
var m = '<div id="claim-list' + claimIndex + '"><label>Claim Type</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Type" />'
var c = '<label>Claim Value</label><input class="form-control" name="RoleClaimList[' + roleIndex + '].ClaimList[' + claimIndex + '].Value" /> </div>'
$("#claim-list" + (claimIndex - 1) + "").append(m);
$("#claim-list" + (claimIndex - 1) + "").append(c);
);

);
</script>


If I add claim it works correctly. Problem start when I add a new role. It should replicate first tree inputs in same order of first one, but it is creating Claim Type first then Claim Value and finally Role Name as this picture:



enter image description here



What I'm doing wrong there? Regards







jquery html5






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 12 '18 at 22:55









JonathanJonathan

1897




1897












  • Consider how your logic is using both roleIndex and claimIndex to determine which #claim-list to append to. You're going to be duplicating claim-list ids

    – Taplar
    Nov 12 '18 at 23:33


















  • Consider how your logic is using both roleIndex and claimIndex to determine which #claim-list to append to. You're going to be duplicating claim-list ids

    – Taplar
    Nov 12 '18 at 23:33

















Consider how your logic is using both roleIndex and claimIndex to determine which #claim-list to append to. You're going to be duplicating claim-list ids

– Taplar
Nov 12 '18 at 23:33






Consider how your logic is using both roleIndex and claimIndex to determine which #claim-list to append to. You're going to be duplicating claim-list ids

– Taplar
Nov 12 '18 at 23:33













1 Answer
1






active

oldest

votes


















0














What's wrong is that you are appending your new #item-list1 div into the existing #item-list0, making it a nested structure.



Same goes to your #claim-list, it became a nested structure:



#item-list0
⤷ #claim-list0
⤷ #claim-list1
⤷ #claim-list2
⤷ #claim-list3
⤷ #item-list1
⤷ #item-list2
⤷ #item-list3


What you should do instead is to append them outside:



  1. Append new #item-listx to <body></body> or whatever parent element.

  2. Append new #claim-list to its corresponding #item-lists.

So it would be your intended structure:



#item-list0
⤷ #claim-list0
⤷ #claim-list1
⤷ #claim-list2

#item-list1
⤷ #claim-list0
⤷ #claim-list1
⤷ #claim-list2


And if you look at it, there comes a few more problems with your code:



  1. You will have duplicated id.


  2. claimIndex will not work properly because you reset it every time #add is clicked (what happens if I click "addClaim" to previous roles after I add new role?)

Below is a sample code that works properly (I think, may not actually be your use case). I have restructured it so that it can be easily understood without much explanation. Please edit as needed to suit your actual code base:






var roleIndex = 0;

$('#add')
.on('click', addRole) // Add onclick handler
.trigger('click'); // Trigger it on execution to create the first set

function addRole()
roleIndex += 1;

// Set `claimIndex` here, not outside of the scope
// because you need it in each separate added role
// so that the claimIndex of each role can correctly counts independently
var claimIndex = 0,
roleClaimList = 'RoleClaimList[' + roleIndex + ']';

var $itemList = $('<div></div>')
.addClass('form-group')
.attr('id', 'item-list-' + roleIndex);

var $roleLabel = $('<label></label>')
.text('Role Name')
.appendTo($itemList);

var $roleInput = $('<input>')
.addClass('form-control roles')
.attr('asp-for', roleClaimList + '.Role.Name')
.appendTo($itemList);

var $addClaimButton = $('<a></a>')
.text('Add another claim')
.attr('href', '#')
.addClass('addClaim')
.on('click', addClaim)
.appendTo($itemList);

$addClaimButton.trigger('click');

$itemList.insertBefore(this);

// Create this function here, not outside
// because it needs the `claimIndex` in scope
function addClaim(e)
e.preventDefault();
claimIndex += 1;

var $claimGroup = $('<div></div>')
.attr('id', 'claim-list-' + roleIndex + '-' + claimIndex)
.insertBefore($addClaimButton);

var $typeLabel = $('<label></label')
.text('Claim Type')
.appendTo($claimGroup);

var $typeInput = $('<input>')
.addClass('form-control claimType')
.attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Type')
.appendTo($claimGroup);

var $valueLabel = $('<label></label')
.text('Claim Value')
.appendTo($claimGroup);

var $valueInput = $('<input>')
.addClass('form-control claimValue')
.attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Value')
.appendTo($claimGroup);


<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="form-group" id="item-list-0"></div>
<a href="#" id="add">Add another role</a>





To know more about scoping, read this amazing answer.






share|improve this answer
























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53271285%2fappending-html-create-inputs-with-different-order%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    What's wrong is that you are appending your new #item-list1 div into the existing #item-list0, making it a nested structure.



    Same goes to your #claim-list, it became a nested structure:



    #item-list0
    ⤷ #claim-list0
    ⤷ #claim-list1
    ⤷ #claim-list2
    ⤷ #claim-list3
    ⤷ #item-list1
    ⤷ #item-list2
    ⤷ #item-list3


    What you should do instead is to append them outside:



    1. Append new #item-listx to <body></body> or whatever parent element.

    2. Append new #claim-list to its corresponding #item-lists.

    So it would be your intended structure:



    #item-list0
    ⤷ #claim-list0
    ⤷ #claim-list1
    ⤷ #claim-list2

    #item-list1
    ⤷ #claim-list0
    ⤷ #claim-list1
    ⤷ #claim-list2


    And if you look at it, there comes a few more problems with your code:



    1. You will have duplicated id.


    2. claimIndex will not work properly because you reset it every time #add is clicked (what happens if I click "addClaim" to previous roles after I add new role?)

    Below is a sample code that works properly (I think, may not actually be your use case). I have restructured it so that it can be easily understood without much explanation. Please edit as needed to suit your actual code base:






    var roleIndex = 0;

    $('#add')
    .on('click', addRole) // Add onclick handler
    .trigger('click'); // Trigger it on execution to create the first set

    function addRole()
    roleIndex += 1;

    // Set `claimIndex` here, not outside of the scope
    // because you need it in each separate added role
    // so that the claimIndex of each role can correctly counts independently
    var claimIndex = 0,
    roleClaimList = 'RoleClaimList[' + roleIndex + ']';

    var $itemList = $('<div></div>')
    .addClass('form-group')
    .attr('id', 'item-list-' + roleIndex);

    var $roleLabel = $('<label></label>')
    .text('Role Name')
    .appendTo($itemList);

    var $roleInput = $('<input>')
    .addClass('form-control roles')
    .attr('asp-for', roleClaimList + '.Role.Name')
    .appendTo($itemList);

    var $addClaimButton = $('<a></a>')
    .text('Add another claim')
    .attr('href', '#')
    .addClass('addClaim')
    .on('click', addClaim)
    .appendTo($itemList);

    $addClaimButton.trigger('click');

    $itemList.insertBefore(this);

    // Create this function here, not outside
    // because it needs the `claimIndex` in scope
    function addClaim(e)
    e.preventDefault();
    claimIndex += 1;

    var $claimGroup = $('<div></div>')
    .attr('id', 'claim-list-' + roleIndex + '-' + claimIndex)
    .insertBefore($addClaimButton);

    var $typeLabel = $('<label></label')
    .text('Claim Type')
    .appendTo($claimGroup);

    var $typeInput = $('<input>')
    .addClass('form-control claimType')
    .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Type')
    .appendTo($claimGroup);

    var $valueLabel = $('<label></label')
    .text('Claim Value')
    .appendTo($claimGroup);

    var $valueInput = $('<input>')
    .addClass('form-control claimValue')
    .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Value')
    .appendTo($claimGroup);


    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    <div class="form-group" id="item-list-0"></div>
    <a href="#" id="add">Add another role</a>





    To know more about scoping, read this amazing answer.






    share|improve this answer





























      0














      What's wrong is that you are appending your new #item-list1 div into the existing #item-list0, making it a nested structure.



      Same goes to your #claim-list, it became a nested structure:



      #item-list0
      ⤷ #claim-list0
      ⤷ #claim-list1
      ⤷ #claim-list2
      ⤷ #claim-list3
      ⤷ #item-list1
      ⤷ #item-list2
      ⤷ #item-list3


      What you should do instead is to append them outside:



      1. Append new #item-listx to <body></body> or whatever parent element.

      2. Append new #claim-list to its corresponding #item-lists.

      So it would be your intended structure:



      #item-list0
      ⤷ #claim-list0
      ⤷ #claim-list1
      ⤷ #claim-list2

      #item-list1
      ⤷ #claim-list0
      ⤷ #claim-list1
      ⤷ #claim-list2


      And if you look at it, there comes a few more problems with your code:



      1. You will have duplicated id.


      2. claimIndex will not work properly because you reset it every time #add is clicked (what happens if I click "addClaim" to previous roles after I add new role?)

      Below is a sample code that works properly (I think, may not actually be your use case). I have restructured it so that it can be easily understood without much explanation. Please edit as needed to suit your actual code base:






      var roleIndex = 0;

      $('#add')
      .on('click', addRole) // Add onclick handler
      .trigger('click'); // Trigger it on execution to create the first set

      function addRole()
      roleIndex += 1;

      // Set `claimIndex` here, not outside of the scope
      // because you need it in each separate added role
      // so that the claimIndex of each role can correctly counts independently
      var claimIndex = 0,
      roleClaimList = 'RoleClaimList[' + roleIndex + ']';

      var $itemList = $('<div></div>')
      .addClass('form-group')
      .attr('id', 'item-list-' + roleIndex);

      var $roleLabel = $('<label></label>')
      .text('Role Name')
      .appendTo($itemList);

      var $roleInput = $('<input>')
      .addClass('form-control roles')
      .attr('asp-for', roleClaimList + '.Role.Name')
      .appendTo($itemList);

      var $addClaimButton = $('<a></a>')
      .text('Add another claim')
      .attr('href', '#')
      .addClass('addClaim')
      .on('click', addClaim)
      .appendTo($itemList);

      $addClaimButton.trigger('click');

      $itemList.insertBefore(this);

      // Create this function here, not outside
      // because it needs the `claimIndex` in scope
      function addClaim(e)
      e.preventDefault();
      claimIndex += 1;

      var $claimGroup = $('<div></div>')
      .attr('id', 'claim-list-' + roleIndex + '-' + claimIndex)
      .insertBefore($addClaimButton);

      var $typeLabel = $('<label></label')
      .text('Claim Type')
      .appendTo($claimGroup);

      var $typeInput = $('<input>')
      .addClass('form-control claimType')
      .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Type')
      .appendTo($claimGroup);

      var $valueLabel = $('<label></label')
      .text('Claim Value')
      .appendTo($claimGroup);

      var $valueInput = $('<input>')
      .addClass('form-control claimValue')
      .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Value')
      .appendTo($claimGroup);


      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

      <div class="form-group" id="item-list-0"></div>
      <a href="#" id="add">Add another role</a>





      To know more about scoping, read this amazing answer.






      share|improve this answer



























        0












        0








        0







        What's wrong is that you are appending your new #item-list1 div into the existing #item-list0, making it a nested structure.



        Same goes to your #claim-list, it became a nested structure:



        #item-list0
        ⤷ #claim-list0
        ⤷ #claim-list1
        ⤷ #claim-list2
        ⤷ #claim-list3
        ⤷ #item-list1
        ⤷ #item-list2
        ⤷ #item-list3


        What you should do instead is to append them outside:



        1. Append new #item-listx to <body></body> or whatever parent element.

        2. Append new #claim-list to its corresponding #item-lists.

        So it would be your intended structure:



        #item-list0
        ⤷ #claim-list0
        ⤷ #claim-list1
        ⤷ #claim-list2

        #item-list1
        ⤷ #claim-list0
        ⤷ #claim-list1
        ⤷ #claim-list2


        And if you look at it, there comes a few more problems with your code:



        1. You will have duplicated id.


        2. claimIndex will not work properly because you reset it every time #add is clicked (what happens if I click "addClaim" to previous roles after I add new role?)

        Below is a sample code that works properly (I think, may not actually be your use case). I have restructured it so that it can be easily understood without much explanation. Please edit as needed to suit your actual code base:






        var roleIndex = 0;

        $('#add')
        .on('click', addRole) // Add onclick handler
        .trigger('click'); // Trigger it on execution to create the first set

        function addRole()
        roleIndex += 1;

        // Set `claimIndex` here, not outside of the scope
        // because you need it in each separate added role
        // so that the claimIndex of each role can correctly counts independently
        var claimIndex = 0,
        roleClaimList = 'RoleClaimList[' + roleIndex + ']';

        var $itemList = $('<div></div>')
        .addClass('form-group')
        .attr('id', 'item-list-' + roleIndex);

        var $roleLabel = $('<label></label>')
        .text('Role Name')
        .appendTo($itemList);

        var $roleInput = $('<input>')
        .addClass('form-control roles')
        .attr('asp-for', roleClaimList + '.Role.Name')
        .appendTo($itemList);

        var $addClaimButton = $('<a></a>')
        .text('Add another claim')
        .attr('href', '#')
        .addClass('addClaim')
        .on('click', addClaim)
        .appendTo($itemList);

        $addClaimButton.trigger('click');

        $itemList.insertBefore(this);

        // Create this function here, not outside
        // because it needs the `claimIndex` in scope
        function addClaim(e)
        e.preventDefault();
        claimIndex += 1;

        var $claimGroup = $('<div></div>')
        .attr('id', 'claim-list-' + roleIndex + '-' + claimIndex)
        .insertBefore($addClaimButton);

        var $typeLabel = $('<label></label')
        .text('Claim Type')
        .appendTo($claimGroup);

        var $typeInput = $('<input>')
        .addClass('form-control claimType')
        .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Type')
        .appendTo($claimGroup);

        var $valueLabel = $('<label></label')
        .text('Claim Value')
        .appendTo($claimGroup);

        var $valueInput = $('<input>')
        .addClass('form-control claimValue')
        .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Value')
        .appendTo($claimGroup);


        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

        <div class="form-group" id="item-list-0"></div>
        <a href="#" id="add">Add another role</a>





        To know more about scoping, read this amazing answer.






        share|improve this answer















        What's wrong is that you are appending your new #item-list1 div into the existing #item-list0, making it a nested structure.



        Same goes to your #claim-list, it became a nested structure:



        #item-list0
        ⤷ #claim-list0
        ⤷ #claim-list1
        ⤷ #claim-list2
        ⤷ #claim-list3
        ⤷ #item-list1
        ⤷ #item-list2
        ⤷ #item-list3


        What you should do instead is to append them outside:



        1. Append new #item-listx to <body></body> or whatever parent element.

        2. Append new #claim-list to its corresponding #item-lists.

        So it would be your intended structure:



        #item-list0
        ⤷ #claim-list0
        ⤷ #claim-list1
        ⤷ #claim-list2

        #item-list1
        ⤷ #claim-list0
        ⤷ #claim-list1
        ⤷ #claim-list2


        And if you look at it, there comes a few more problems with your code:



        1. You will have duplicated id.


        2. claimIndex will not work properly because you reset it every time #add is clicked (what happens if I click "addClaim" to previous roles after I add new role?)

        Below is a sample code that works properly (I think, may not actually be your use case). I have restructured it so that it can be easily understood without much explanation. Please edit as needed to suit your actual code base:






        var roleIndex = 0;

        $('#add')
        .on('click', addRole) // Add onclick handler
        .trigger('click'); // Trigger it on execution to create the first set

        function addRole()
        roleIndex += 1;

        // Set `claimIndex` here, not outside of the scope
        // because you need it in each separate added role
        // so that the claimIndex of each role can correctly counts independently
        var claimIndex = 0,
        roleClaimList = 'RoleClaimList[' + roleIndex + ']';

        var $itemList = $('<div></div>')
        .addClass('form-group')
        .attr('id', 'item-list-' + roleIndex);

        var $roleLabel = $('<label></label>')
        .text('Role Name')
        .appendTo($itemList);

        var $roleInput = $('<input>')
        .addClass('form-control roles')
        .attr('asp-for', roleClaimList + '.Role.Name')
        .appendTo($itemList);

        var $addClaimButton = $('<a></a>')
        .text('Add another claim')
        .attr('href', '#')
        .addClass('addClaim')
        .on('click', addClaim)
        .appendTo($itemList);

        $addClaimButton.trigger('click');

        $itemList.insertBefore(this);

        // Create this function here, not outside
        // because it needs the `claimIndex` in scope
        function addClaim(e)
        e.preventDefault();
        claimIndex += 1;

        var $claimGroup = $('<div></div>')
        .attr('id', 'claim-list-' + roleIndex + '-' + claimIndex)
        .insertBefore($addClaimButton);

        var $typeLabel = $('<label></label')
        .text('Claim Type')
        .appendTo($claimGroup);

        var $typeInput = $('<input>')
        .addClass('form-control claimType')
        .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Type')
        .appendTo($claimGroup);

        var $valueLabel = $('<label></label')
        .text('Claim Value')
        .appendTo($claimGroup);

        var $valueInput = $('<input>')
        .addClass('form-control claimValue')
        .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Value')
        .appendTo($claimGroup);


        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

        <div class="form-group" id="item-list-0"></div>
        <a href="#" id="add">Add another role</a>





        To know more about scoping, read this amazing answer.






        var roleIndex = 0;

        $('#add')
        .on('click', addRole) // Add onclick handler
        .trigger('click'); // Trigger it on execution to create the first set

        function addRole()
        roleIndex += 1;

        // Set `claimIndex` here, not outside of the scope
        // because you need it in each separate added role
        // so that the claimIndex of each role can correctly counts independently
        var claimIndex = 0,
        roleClaimList = 'RoleClaimList[' + roleIndex + ']';

        var $itemList = $('<div></div>')
        .addClass('form-group')
        .attr('id', 'item-list-' + roleIndex);

        var $roleLabel = $('<label></label>')
        .text('Role Name')
        .appendTo($itemList);

        var $roleInput = $('<input>')
        .addClass('form-control roles')
        .attr('asp-for', roleClaimList + '.Role.Name')
        .appendTo($itemList);

        var $addClaimButton = $('<a></a>')
        .text('Add another claim')
        .attr('href', '#')
        .addClass('addClaim')
        .on('click', addClaim)
        .appendTo($itemList);

        $addClaimButton.trigger('click');

        $itemList.insertBefore(this);

        // Create this function here, not outside
        // because it needs the `claimIndex` in scope
        function addClaim(e)
        e.preventDefault();
        claimIndex += 1;

        var $claimGroup = $('<div></div>')
        .attr('id', 'claim-list-' + roleIndex + '-' + claimIndex)
        .insertBefore($addClaimButton);

        var $typeLabel = $('<label></label')
        .text('Claim Type')
        .appendTo($claimGroup);

        var $typeInput = $('<input>')
        .addClass('form-control claimType')
        .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Type')
        .appendTo($claimGroup);

        var $valueLabel = $('<label></label')
        .text('Claim Value')
        .appendTo($claimGroup);

        var $valueInput = $('<input>')
        .addClass('form-control claimValue')
        .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Value')
        .appendTo($claimGroup);


        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

        <div class="form-group" id="item-list-0"></div>
        <a href="#" id="add">Add another role</a>





        var roleIndex = 0;

        $('#add')
        .on('click', addRole) // Add onclick handler
        .trigger('click'); // Trigger it on execution to create the first set

        function addRole()
        roleIndex += 1;

        // Set `claimIndex` here, not outside of the scope
        // because you need it in each separate added role
        // so that the claimIndex of each role can correctly counts independently
        var claimIndex = 0,
        roleClaimList = 'RoleClaimList[' + roleIndex + ']';

        var $itemList = $('<div></div>')
        .addClass('form-group')
        .attr('id', 'item-list-' + roleIndex);

        var $roleLabel = $('<label></label>')
        .text('Role Name')
        .appendTo($itemList);

        var $roleInput = $('<input>')
        .addClass('form-control roles')
        .attr('asp-for', roleClaimList + '.Role.Name')
        .appendTo($itemList);

        var $addClaimButton = $('<a></a>')
        .text('Add another claim')
        .attr('href', '#')
        .addClass('addClaim')
        .on('click', addClaim)
        .appendTo($itemList);

        $addClaimButton.trigger('click');

        $itemList.insertBefore(this);

        // Create this function here, not outside
        // because it needs the `claimIndex` in scope
        function addClaim(e)
        e.preventDefault();
        claimIndex += 1;

        var $claimGroup = $('<div></div>')
        .attr('id', 'claim-list-' + roleIndex + '-' + claimIndex)
        .insertBefore($addClaimButton);

        var $typeLabel = $('<label></label')
        .text('Claim Type')
        .appendTo($claimGroup);

        var $typeInput = $('<input>')
        .addClass('form-control claimType')
        .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Type')
        .appendTo($claimGroup);

        var $valueLabel = $('<label></label')
        .text('Claim Value')
        .appendTo($claimGroup);

        var $valueInput = $('<input>')
        .addClass('form-control claimValue')
        .attr('asp-for', roleClaimList + '.ClaimList[' + claimIndex + '].Value')
        .appendTo($claimGroup);


        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

        <div class="form-group" id="item-list-0"></div>
        <a href="#" id="add">Add another role</a>






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 14 '18 at 1:35

























        answered Nov 13 '18 at 2:30









        Yong QuanYong Quan

        2,0591621




        2,0591621



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53271285%2fappending-html-create-inputs-with-different-order%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Use pre created SQLite database for Android project in kotlin

            Darth Vader #20

            Ondo