Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unique name for Add More input

Tags:

I am trying to create an add more button which will create a new input field. However, I would like to have an unique name set for it.

I tried to search up for an answer, but this does not answer my question.

So, basically what I tried to make my namefield unique is to use the php method rand(). The concept is that - when the add more button is clicked, it will have a name attached to the number given to me by rand().

However, what happens is that it takes the value generated by rand() and applies it to all the names of all the inputs generated.

This is my code and what I tried:

HTML:

<div class="field_wrapper">
    <div>
        <input type="text" name="field_name[<?php echo rand(); ?>]" value=""/>
        <a href="javascript:void(0);" class="add_button" title="Add field">Add More</a>
    </div>
</div>

JQUERY / JAVASCRIPT:

<script type="text/javascript">
$(document).ready(function(){
    var maxField = 100; //Input fields increment limitation
    var addButton = $('.add_button'); //Add button selector
    var wrapper = $('.field_wrapper'); //Input field wrapper
    var fieldHTML = '<div><input type="text" name="field_name[<?php echo rand(); ?>]" value=""/><a href="javascript:void(0);" class="remove_button">Remove</a></div>'; //New input field html 
    var x = 1; //Initial field counter is 1

    //Once add button is clicked
    $(addButton).click(function(){
        //Check maximum number of input fields
        if(x < maxField){ 
            x++; //Increment field counter
            $(wrapper).append(fieldHTML); //Add field html
        }
    });

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

As you can see, the first field generates the number as intended. If you click on the add more, the second field does create an unique number. However, if you click add more once again, the third field copies the same name as the 2nd field.

How do I go about achieving what I want and why is rand() not generating a new code?

Also, does rand() guarantee me that it will be an unique ID or is there a chance for it to repeat the same number?

If it does repeat, then what would be the best approach to take to make it as unique as possible?

like image 967
Gosi Avatar asked Aug 19 '19 07:08

Gosi


2 Answers

If you generate random name with PHP it is done once on the server. Your JS code then copies the same element. What you need is to generate unique names with js.

Avoid random if you can, theoretically, you can hit the same number and run into mysterious bugs.

var generateField = function(name)
{
     return '<div><input type="text" name="'+name+'" value=""/><a href="javascript:void(0);" class="remove_button">Remove</a></div>'; //New input field html 
}

//Once add button is clicked
$(addButton).click(function(){
    //Check maximum number of input fields
    if(x < maxField){ 
        x++; //Increment field counter
        $(wrapper).append(generateField('field_name['+x+']' ) ); //Add field html
    }
});
like image 80
Eriks Klotins Avatar answered Sep 28 '22 10:09

Eriks Klotins


Random does not necessarily mean unique, even if collisions would be extremely rare. This solution simply increments a totalFieldsCreated variable to get the next unique number (up to the maximum value JavaScript can provide.)

The new fields are created dynamically instead of using a fixed string of HTML. (This technique is more flexible.)

$(document).ready(function() {

  // Defines global identifiers
  let
    currentFieldCount = 1,
    totalFieldsCreated = 1;
  const
    maxFieldCount = 100,
    addButton = $('.add_button'),
    wrapper = $('.field_wrapper');

  // Calls `addField` when addButton is clicked
  $(addButton).click(addField);

  // Executes anonymous function when `Remove` is clicked, which removes
  //   the parent div, and decrements (and logs) `currentFieldCount`
  $(wrapper).on('click', '.remove_button', function(e) {
    e.preventDefault();
    $(this).parent('div').remove();
    currentFieldCount--;
    console.log(`currentFieldCount: ${currentFieldCount}`);
  });

  // Defines the `addField` function
  function addField(){

    // Makes sure that `currentFieldCount` and `totalFieldsCreated` 
    //   are not at maximum before proceeding
    if(
      currentFieldCount < maxFieldCount && 
      totalFieldsCreated < Number.MAX_VALUE
    ){

      // Creates an input element, increments `totalFieldsCreated`,
      //   and uses the incremented value in the input's `name` attribute
      const input = document.createElement("input");
      input.type = "text";
      input.name = "field" + ++totalFieldsCreated;
      input.value = "";

      // Creates an anchor element with the `remove_button` class
      const a = document.createElement("a");
      a.href = "javascript:void(0);";
      a.classList.add("remove_button");
      a.title = "remove";
      a.innerHTML = "Remove";
      
      // Adds the new elements to the DOM, and increments `currentFieldCount`
      const div = document.createElement("div");
      div.appendChild(input);
      div.appendChild(a);
      $(wrapper).append(div);
      currentFieldCount++;

      // Logs the new values of both variables 
      console.log(
        `currentFieldCount: ${currentFieldCount},`,
        `totalFieldsCreated ${totalFieldsCreated}`
      );
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="field_wrapper">
  <div>
    <input type="text" name="field1" value="" />
    <a href="javascript:void(0);" class="add_button" title="Add field">Add More</a>
  </div>
</div>
like image 43
Cat Avatar answered Sep 28 '22 11:09

Cat