Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using jQuery to dynamically add form fields (or fieldsets) based on a dropdown box value

As the title says, what I am trying to do is to have jQuery add a number of extra fieldsets based on the value selected in a drop-down box. For example, when the page loads, the drop-down has a default value of 1, and the default fieldset is displayed. Now, if the user selects a different value in that drop-down, the number of fieldsets should be adjusted accordingly, through cloning (I suppose this would be the best solution). Here's what I have so far:

Drop-down box code ...

<select id="itemCount" name="itemCount">
 <option value="1">1 item</option>
 <option value="2">2 items</option>
 <option value="3">3 items</option>
 <option value="4">4 items</option>
 <option value="5">5 items</option>
 <option value="6">6 items</option>
</select>

... the jQuery change listener ...

$(document).ready(function() {
 $("#itemCount").change(function(){
  var itemCountVal = jQuery(this).val();
  $("#item_dup_1").fieldsManage(itemCountVal);
 });
});

... and the function itself (it is actually based on a jQuery plugin which I thought was a good starting point for what I need):

jQuery.fn.fieldsManage = function (number) {
  var clone,
  objTemplate = source.clone(true),
  source = jQuery(this),
  maxClones = number - 1,
  clones = [];

  if (clones.length < maxClones) {
    while (clones.length < maxClones) {
      clone = objTemplate.clone(true).insertAfter(clones[clones.length - 1] || source);
      clones.push(clone);
    }
  }

  if (clones.length > maxClones) {
    // Fieldsets removal function goes here.
  }
}

The object that is being cloned is something like <fieldset id="item_dup_1"><input><input><input></fieldset>. I don't think it is necessary to show the full code for it as well.

This works like a charm for the first change, but if the user changes the value again, that's when things go wrong, and instead of showing the correct number of fieldsets, it shows more. It looks like it is calculating the number of fieldsets needed starting from scratch, disregarding the fact that fieldsets have already been added, and this is what my problem actually is. I also have a function (not shown here just to keep the question clear and as short as possible) that asigns new IDs to the cloned fieldset to prevent duplicate IDs and which works without a hitch.

I am convinced that I am doing something wrong, but I have been banging my head against a wall with this for two days now, trying to find what it is with no luck whatsoever so, any help would be more than appreciated !

Thanks in advance !

like image 965
Valentin Flachsel Avatar asked Dec 12 '09 16:12

Valentin Flachsel


1 Answers

I don't like the solution of Nate B.

  • it needs an additional container element
  • recreates everything, thus loosing data already entered
  • creates a maintenance problem: html markup of the fieldset is duplicated (once in HTML, once as string for append)
  • creates invalid id's for the fieldsets (id's can't start with a number)

This does what you want and similar to what you did. Keeps only the ids in a data attribute on the original element (instead of keeping the whole clone object which could use massive amounts of memory). Keeps all values already entered. Doesn't recreate everything if you change from e.g. 3 to 5. Instead only generates two new fieldsets. Removes them in reverse order they where created.

jQuery.fn.fieldsManage = function (number) {
    var ele = $(this);
    var clones = ele.data("clones");
    clones = clones ? clones : new Array(ele.attr("id"));
    if (clones.length < number) {
        var clone;
        while(clones.length < number) {
            clone = ele.clone(true);
            var id = clones[0]+clones.length;
            clone.attr("id", id);
            $("#"+clones[clones.length-1]).after(clone);
            clones.push(id);
        }
    } else {
        while(clones.length > number) {
            $("#"+clones.pop()).remove();
        }
    }
    ele.data("clones", clones);
}

$(document).ready(function() {
    $("#itemCount").change(function() {
        $("#item_dup_1").fieldsManage(this.value);
    });
});
like image 73
jitter Avatar answered Oct 22 '22 11:10

jitter