0

first of all i'm not a programmer of any kind, so i please need you to fix my issue.

I have a contact form which have inside a place where i can add more input fields till a maximum of 10. Each field i add it has inside the code a class that i called "pers", and i want that this class pers has an incremental number near to it, as pers1, 2, 3 and so go on.

Getting the incremental value was easy but the problem is that the class "pers" wont update the variable keeping the first number on document load.

Here is the code

<script type="text/javascript">
  window.s = 1;
</script>

<script type="text/javascript">
  $(document).ready(function() {
    var addButton = $('.add_button');
    var wrapper = $('.field_wrapper');
    var maxField = 10;
    var fieldHTML = '<div style="margin-top:5px;"><input type="text3" name="pers' + window.s + '" placeholder="Nome e Cognome"/><input type="time" style=margin-left:3.5px; autocomplete="off"><input type="time" style=margin-left:3.5px; autocomplete="off"><a href="javascript:void(0);"class="remove_button" title="Rimuovi"><img src="IMG/less_icon.png"></a></div>';

    $(addButton).click(function() {
      if (window.s < maxField) {
        window.s++; //Increment field counter
        $(wrapper).append(fieldHTML); //Add field html
      }
    });

    $(wrapper).on('click', '.remove_button', function(e) {
      e.preventDefault();
      $(this).parent('div').remove(); //Remove field html
      s--; //Decrement field counter
    });
  });
</script>

There is a global variable "window.s" because it was my last try to get the var updated.

The fields adds correctly till 10 as it should be, but the "window.s" or when it was only "s" still keeps his first value of 1, and so "pers" is always "pers1". I thought that exposing a global variable i would have fix the problem, but nothing.

What am i doing wrong?

Thank you very much for your help guys.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • For what reason do you need to have the increment? The point of `class` attributes is that they should be the same across multiple elements in order to group them. Similarly, keep the input `name` attribuites the same and work with the values as an array on the server side when the form is submit. – Rory McCrossan Jun 28 '22 at 10:49
  • `var fieldHTML = ........`. You never update this variable, so it stays the string containing pers1. Update fieldHTML every time you update `s`. As written, you only create it once, at startup and reuse that HTML string all the time. – Shilly Jun 28 '22 at 10:53
  • Because it is a direct form, it sends data directly to the email as pdf. So you mean to get the same class and then make an array through php? ( Because i'm not using a database being direct ) – Giovanni De Miccoli Jun 28 '22 at 10:56

2 Answers2

1

The problem with your code is because you only set fieldHTML once, when the page loads. At this point window.s is 1, so this is the value that's used every time you reference fieldHTML. The quick fix to this would be to put the fieldHTML definition inside the click() event handler.

However the better approach it to entirely remove the need for the incremental variable at all. Use the same name on all the fields you dynamically generate. This way you don't need to maintain the count (eg. if there have been 5 added and someone deletes the 3rd one, you'll currently end up with 2 per5 elements). Because of this it also simplifies the JS logic. In addition you should put the HTML to clone in a <template> element, not the JS, so that there's no cross-contamination of the codebase.

Here's a working example of the changes I mention:

jQuery($ => {
  var $addButton = $('.add_button');
  var $wrapper = $('.field_wrapper');
  var maxFields = 10;
  var fieldHTML = $('#field_template').html();

  $addButton.click(() => {
    if ($('.field_wrapper > div').length < maxFields) {
      $wrapper.append(fieldHTML);
    }
  });

  $wrapper.on('click', '.remove_button', e => {
    e.preventDefault();
    $(e.target).closest('div').remove();
  });
});
.field_wrapper>div {
  margin-top: 5px;
}

.field_wrapper input.time {
  margin-left: 3.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<button class="add_button">Add</button>
<div class="field_wrapper"></div>

<template id="field_template">
  <div>
    <input type="text3" name="pers[]" placeholder="Nome e Cognome" />
    <input type="time" name="time1[]" class="time" autocomplete="off" />
    <input type="time" name="time2[]" class="time" autocomplete="off" />
    <a href="#" class="remove_button" title="Rimuovi">
      <img src="IMG/less_icon.png">
    </a>
  </div>
</template>

You can then receive all the input values as an array in your PHP code, like this.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • Thank you very much Rory! Anyway i did find more easy the @Saroj solution even if i will keep all of your replies that are very helpful! Thank you thank you – Giovanni De Miccoli Jun 28 '22 at 11:11
0

It's because you have not used the updated value there.

First, you assign a value to window.s, and then you create a variable that uses the value of window.s from the initial state, and on each addition, it just appends the same fieldHtml. So, you are getting the same value.

Here is the answer, you are looking:

<div><button class="add_button">click me</button></div>
<div class="field_wrapper"></div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script type="text/javascript">
  window.s = 1;
</script>

<script type="text/javascript">
  $(document).ready(function() {
    var addButton = $('.add_button');
    var wrapper = $('.field_wrapper');
    var maxField = 10;


    $(addButton).click(function() {
      if (window.s < maxField) {
        window.s++; //Increment field counter
        let fieldHTML = generateLine(window.s);
        $(wrapper).append(fieldHTML); //Add field html
      }
    });

    $(wrapper).on('click', '.remove_button', function(e) {
      e.preventDefault();
      $(this).parent('div').remove(); //Remove field html
      s--; //Decrement field counter
    });
  });
  
  function generateLine(lineNumber){
      return '<div style="margin-top:5px;"><input type="text3" name="pers' + lineNumber + '" placeholder="Nome e Cognome"/><input type="time" style=margin-left:3.5px; autocomplete="off"><input type="time" style=margin-left:3.5px; autocomplete="off"><a href="javascript:void(0);"class="remove_button" title="Rimuovi"><img src="IMG/less_icon.png"></a></div>';
  }
</script>
Saroj Shrestha
  • 2,696
  • 4
  • 21
  • 45