Dynamically Add and Remove Form Item using jQuery clone() Method Tutorial

In this article, I will be discussing about how to create an Add and Remove Form Item Feature in web-application using jQuery's clone() method. This kind of feature is commonly applied to a project which has a process of saving multiple data at once in the database. There are lots of ideas and techniques you can create to achieve this feature with the help of jQuery, but I found this solution more simple and easiest in my experience.

Below, I have provided a simple PHP Web Application which contains a form for Contact Directories which allows the users to add multiple set of input dynamically. The form items/sets contain the fields that are needed and each of these items has a 'remove button' using an 'x' icon button at the upper-right. The remove button allows the user to remove the item. It has also contained some features that are commonly included in submitting a form such as preventing submitting the form when no item is listed and if required fields are empty. The application only displays the submitted data and there is no database included.

Getting Started

To run the application you must have a local server such as XAMPP in order to run PHP Scripts in your device.

Using XAMPP:

Download and Install XAMPP. After that, open the XAMPP's Control Panel and start the Apache. Then create a new directory in your xampp/htdocs directory.

Libraries/Plugin used: (Download and compile the ff in your source code directory)

Creating Default Page Interface

The script below is the code of our default page which is the index.php. This file contains the contact form.

  1. <!DOCTYPE html>
  2. <html lang="en">
  3.  
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Cloning Element</title>
  8. <link rel="stylesheet" href="./Font-Awesome-master/css/all.min.css">
  9. <link rel="stylesheet" href="./css/bootstrap.min.css">
  10. <script src="./js/jquery-3.6.0.min.js"></script>
  11. <script src="./js/bootstrap.min.js"></script>
  12. <script src="./js/script.js"></script>
  13. :root {
  14. --bs-success-rgb: 71, 222, 152 !important;
  15. }
  16.  
  17. html,
  18. body {
  19. height: 100%;
  20. width: 100%;
  21. font-family: Apple Chancery, cursive;
  22. }
  23.  
  24. .btn-info.text-light:hover,
  25. .btn-info.text-light:focus {
  26. background: #000;
  27. }
  28. </style>
  29. </head>
  30.  
  31. <body class="bg-light">
  32. <nav class="navbar navbar-expand-lg navbar-dark bg-dark bg-gradient" id="topNavBar">
  33. <div class="container">
  34. <a class="navbar-brand" href="https://sourcecodester.com">
  35. Sourcecodester
  36. </a>
  37.  
  38. <div>
  39. <b class="text-light">Cloning Element</b>
  40. </div>
  41. </div>
  42. </nav>
  43. <div class="container py-5" id="page-container">
  44. <div class="card rounded-0 shadow">
  45. <div class="card-header">
  46. <h4 class="card-title"> Simple Contact Information Form</h4>
  47. </div>
  48. <div class="card-body">
  49. <form action="submitted_data.php" method="POST" id="contact-form">
  50. <div class="row align-items-center" id="item-card">
  51. <div class="col-lg-4 col-md-6 col-sm-12 item mb-3 h-100">
  52. <div class="card rounded-0 shadow h-100">
  53. <div class="card-body h-100">
  54. <div class="container-fluid">
  55. <div class="w-100 text-end">
  56. <button class="btn btn-outline-danger btn-sm rounded-0 remove-item" type="button"><i class="fa fa-times"></i></button>
  57. </div>
  58. <div class="form-group">
  59. <label class="control-label text-muted">Name</label>
  60. <input type="text" name="name[]" class="form-control form-control-sm rounded-0" required>
  61. </div>
  62. <div class="form-group">
  63. <label class="control-label text-muted">Email</label>
  64. <input type="email" name="email[]" class="form-control form-control-sm rounded-0" required>
  65. </div>
  66. <div class="form-group">
  67. <label class="control-label text-muted">Contact #</label>
  68. <input type="text" name="contact[]" class="form-control form-control-sm rounded-0" required>
  69. </div>
  70. <div class="form-group">
  71. <label class="control-label text-muted">Address</label>
  72. <textarea name="address[]" rows="3" style="resize:none" class="form-control form-control-sm rounded-0" required></textarea>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. <div class="col-lg-4 col-md-6 col-sm-12 h-100" id="new_item">
  79. <div class="card rounded-0 shadow h-100">
  80. <div class="card-body h-100">
  81. <div class="container-fluid h-100">
  82. <a href="javascript:void(0)" id="new-item-btn" class="text-dark fw-bolder fs-1 h-100 w-100 text-decoration-none">
  83. <div class="d-flex w-100 h-100 align-items-center justify-content-center">
  84. <i class="fa fa-plus"></i>
  85. </div>
  86. </a>
  87. </div>
  88. </div>
  89. </div>
  90. </div>
  91. </div>
  92. <div class="row justify-content-center">
  93. <button class="btn btn-primary bg-gradient col-md-4 btn-large rounded-pill" type="button" id="submit-form">Submit Data</button>
  94. </div>
  95. </form>
  96. </div>
  97. </div>
  98. </div>
  99. </body>
  100. <!--The ELement to be Cloned -->
  101. <noscript id="el-clone">
  102. <div class="col-lg-4 col-md-6 col-sm-12 item mb-3 h-100">
  103. <div class="card rounded-0 shadow h-100">
  104. <div class="card-body h-100">
  105. <div class="container-fluid">
  106. <div class="w-100 text-end">
  107. <button class="btn btn-outline-danger btn-sm rounded-0 remove-item" type="button"><i class="fa fa-times"></i></button>
  108. </div>
  109. <div class="form-group">
  110. <label class="control-label text-muted">Name</label>
  111. <input type="text" name="name[]" class="form-control form-control-sm rounded-0" required>
  112. </div>
  113. <div class="form-group">
  114. <label class="control-label text-muted">Email</label>
  115. <input type="email" name="email[]" class="form-control form-control-sm rounded-0" required>
  116. </div>
  117. <div class="form-group">
  118. <label class="control-label text-muted">Contact #</label>
  119. <input type="text" name="contact[]" class="form-control form-control-sm rounded-0" required>
  120. </div>
  121. <div class="form-group">
  122. <label class="control-label text-muted">Address</label>
  123. <textarea name="address[]" rows="3" style="resize:none" class="form-control form-control-sm rounded-0" required></textarea>
  124. </div>
  125. </div>
  126. </div>
  127. </div>
  128. </div>
  129. <!--The ELement to be Cloned -->
  130.  
  131. </html>

Creating Submitted Data Display Page

This is the page where the page will be redirected when the form is submitted. It contains a table that list all the contact information submitted. This page can be only browse when the form is submitted. Save the scrip below as submitted_data.php.

  1. <?php
  2. // Checks if There is a POST Data
  3. if($_SERVER['REQUEST_METHOD'] != 'POST'){
  4. echo '<script> alert("No data has been submitted."); location.replace("./")</script>';
  5. }else{
  6. extract($_POST);
  7. }
  8. ?>
  9. <!DOCTYPE html>
  10. <html lang="en">
  11.  
  12. <meta charset="UTF-8">
  13. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  14. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  15. <title>Cloning Element</title>
  16. <link rel="stylesheet" href="./Font-Awesome-master/css/all.min.css">
  17. <link rel="stylesheet" href="./css/bootstrap.min.css">
  18. <script src="./js/jquery-3.6.0.min.js"></script>
  19. <script src="./js/bootstrap.min.js"></script>
  20. <script src="./js/script.js"></script>
  21. :root {
  22. --bs-success-rgb: 71, 222, 152 !important;
  23. }
  24.  
  25. html,
  26. body {
  27. height: 100%;
  28. width: 100%;
  29. font-family: Apple Chancery, cursive;
  30. }
  31.  
  32. .btn-info.text-light:hover,
  33. .btn-info.text-light:focus {
  34. background: #000;
  35. }
  36. </style>
  37. </head>
  38.  
  39. <body class="bg-light">
  40. <nav class="navbar navbar-expand-lg navbar-dark bg-dark bg-gradient" id="topNavBar">
  41. <div class="container">
  42. <a class="navbar-brand" href="https://sourcecodester.com">
  43. Sourcecodester
  44. </a>
  45.  
  46. <div>
  47. <b class="text-light">Cloning Element</b>
  48. </div>
  49. </div>
  50. </nav>
  51. <div class="container py-5" id="page-container">
  52. <div class="card rounded-0 shadow">
  53. <div class="card-header">
  54. <div class="d-flex w-100">
  55. <h4 class="card-title col-8"> Submitted Data</h4>
  56. <div class="col-4 text-end">
  57. <a class="btn btn-light rounded-0 border btn-sm" href="./"><i class="fa fa-angle-left"></i> Back</a>
  58. </div>
  59. </div>
  60. </div>
  61. <div class="card-body">
  62. <div class="container-fluid">
  63. <table class="table table-stripped table-bordered">
  64. <col width="5%">
  65. <col width="25%">
  66. <col width="15%">
  67. <col width="15%">
  68. <col width="40%">
  69. <tr class="bg-primary bg-gradient text-light">
  70. <th class="text-center">#</th>
  71. <th class="text-center">Name</th>
  72. <th class="text-center">Email</th>
  73. <th class="text-center">Contact #</th>
  74. <th class="text-center">Address</th>
  75. </tr>
  76. </thead>
  77. <?php
  78. $i = 1;
  79. // Looping all the submitted data
  80. foreach($name as $k => $v):
  81. ?>
  82. <tr>
  83. <td class="px-2 py-1 text-center"><?= $i++; ?></td>
  84. <td class="px-2 py-1"><?= $v ?></td>
  85. <td class="px-2 py-1"><?= $email[$k] ?></td>
  86. <td class="px-2 py-1"><?= $contact[$k] ?></td>
  87. <td class="px-2 py-1"><?= $address[$k] ?></td>
  88. </tr>
  89. <?php endforeach; ?>
  90. </tbody>
  91. </table>
  92. </div>
  93. </div>
  94. </div>
  95. </div>
  96. </body>
  97. </html>

Creating Main Function

The script below is a JavaScript file that contains our jQuery custom functions and event codes. The script includes the codes of cloning an item/set to be added at the form, removing the item/set from the form, and the form check process before submitting the data. Save the file as script.js and in my case, my CSS and JS files are organized by directory which makes this file located inside the JS directory.

  1. // removing the contact Item
  2. function remove_item(_this) {
  3. _this.closest('.item').remove()
  4. }
  5. $(function() {
  6. // Focuses the first Input of Form
  7. $('input[name="name[]"]').first().focus()
  8.  
  9. // Event Lister of Form Item Remove Button when Click
  10. $('.remove-item').click(function() {
  11. remove_item($(this))
  12. })
  13.  
  14. // Adds New Form Item when Add Item has been Clicked
  15. $('#new-item-btn').click(function() {
  16. // cloning the item card from noscript element
  17. var item = $($('noscript#el-clone').html()).clone()
  18.  
  19. // Inserting the new item befor 'Add Item' Card
  20. $('#new_item').before(item)
  21.  
  22. // Focuses the first input in the added item card
  23. item.find('input[name="name[]"]').focus()
  24.  
  25. // Event Lister of added item card Remove Button when Click
  26. item.find('.remove-item').click(function() {
  27. remove_item($(this))
  28. })
  29. })
  30.  
  31. // Event when clicking the Submit Button
  32. $('#submit-form').click(function() {
  33. var form = $('#contact-form')
  34. $(this).attr('disabled', true)
  35. .text("Submitting Data ...")
  36. if ($('#item-card .item').length <= 0) {
  37. // Checks if there is atleast 1 Item Card
  38. alert("No Contact Item Added.")
  39. $(this).attr('disabled', false)
  40. .text("Submit Data")
  41. return false;
  42. } else if (form[0].checkValidity() == false) {
  43. // Checks if All input fields are filled
  44. form[0].reportValidity()
  45. $(this).attr('disabled', false)
  46. .text("Submit Data")
  47. return false;
  48. } else {
  49. // Form Submission
  50. form.submit()
  51. }
  52. })
  53. })

There you go. You can now test the application on your end and check if it working properly and achieves the goal I stated above. If there's an error occurred on your end, review your codes with the codes I provided above. You can also download the source code I created for this tutorial. The download link/button is located after this article.

That ends this tutorial. I hope this will help you with what you are looking for and you'll find it useful with your current or future projects.

Explore more on this website for more Tutorials and Free Source Codes.

Related Links:

Happy Coding :)

Add new comment