简体   繁体   中英

How can I create dynamic controls and put their data into an object?

I created a div and a button. when the button clicked, there will be a group of element(included 1 select box and 2 text inputs) inserted into the div. User can add as many group as they can, when they finished type in data of all the group they added, he can hit save button, which will take the value from each group one by one into the JSON object array. But I am stuck in the part how to get the value from each group, so please help, thank you.

The code for the div and the add group button function -- AddExtra() are listed below:

<div id="roomextra">
</div>

function AddExtra() {
$('#roomextra').append('<div class=extra>' +
'<select id="isInset">' +
'<option value="Inset">Inset</option>' +
'<option value="Offset">OffSet</option>' +
'</select>' + 
'Length(m): <input type="text" id="insetLength">' +
'Width(m): <input type="text" id="insetWidth">' +
'Height(m): <input type="text" id="insetHeight">' +
'</div>');
}

function GetInsetOffSetArray (callBack) {

  var roomIFSDetail = [{
   "IsInset": '' ,
   "Length": '' , 
   "Width": ''  , 
   "Height": ''
  }];

//should get all the value from each group element and write into the array.

callBack(roomIFSDetail);

}

This should just about do it. However, if you're dynamically creating these groups, you'll need to use something other than id. You may want to add a class to them or a data-* attribute. I used a class, in this case. Add those classes to your controls so we know which is which.

var roomIFSDetail = [];
var obj;

// grab all of the divs (groups) and look for my controls in them
$(.extra).each(function(){
  // create object out of select and inputs values
  // the 'this' in the selector is the context. It basically says to use the object
  // from the .each loop to search in. 
  obj = {
           IsInset: $('.isInset', this).find(':selected').val() ,
           Length: $('.insetLength', this).val() ,
           Width: $('.insetWidth', this).val() , 
           Height: $('.insetHeight', this).val()
        }; 
  // add object to array of objects
  roomIFSDetail.push(obj);
});

you'd better not to use id attribute to identity the select and input, name attribute instead. for example

 $('#roomextra').append('<div class=extra>' +
     '<select name="isInset">' +
     '<option value="Inset">Inset</option>' +
     '<option value="Offset">OffSet</option>' +
     '</select>' + 
     'Length(m): <input type="text" name="insetLength">' +
     'Width(m): <input type="text" name="insetWidth">' +
     'Height(m): <input type="text" name="insetHeight">' +
     '</div>');
 }

and then, usr foreach to iterate

 $(".extra").each(function() {
     var $this = $(this);
     var isInset = $this.find("select[name='isInset']").val();
     var insetLength = $this.find("input[name='insetLength']").val();
     // ... and go on
 });

A common problem. A couple things:

  1. You can't use IDs in the section you're going to be repeating, because IDs in the DOM are supposed to be unique.

  2. I prefer to use markup where I'm writing a lot of it, and modify it in code rather than generate it there.

http://jsfiddle.net/b9chris/PZ8sf/

HTML:

<div id=form>
... non-repeating elements go here...

<div id=roomextra>
<div class=extra>

<select name=isInset>
<option>Inset</option>
<option>OffSet</option>
</select>
Length(m): <input id=insetLength>
Width(m): <input id=insetWidth>
Height(m): <input id=insetHeight>

</div>
</div>

</div>

JS:

(function() {
// Get the template
var container = $('#roomextra');
var T = $('div.extra', container);

$('#addGroup').click(function() {
    container.append(T.clone());
});

$('#submit').click(function() {
    var d = {};
    // Fill d with data from the rest of the form

    d.groups = $.map($('div.extra', container), function(tag) {
        var g = {};
        $.each(['isInset', 'insetLength', 'insetWidth', 'insetHeight'], function(i, name) {
            g[name] = $('[name=' + name + ']', tag).val();
        });

        return g;
    });

    // Inspect the data to ensure it's what you wanted
    debugger;
});

})();

So the template that keeps repeating is written in plain old HTML rather than a bunch of JS strings appended to each other. Using name attributes instead of ids keeps with the way these elements typically work without violating any DOM constraints.

You might notice I didn't quote my attributes, took the value attributes out of the options, and took the type attributes out of the inputs, to keep the code a bit DRYer. HTML5 specs don't require quoting your attributes, the option tag's value is whatever the text is if you don't specify a value attribute explicitly, and input tags default to type=text if none is specified, all of which adds up to a quicker read and slimmer HTML.

Use $(".extra").each(function() {

//Pull info out of ctrls here

});

That will iterate through all of your extra divs and allow you to add all values to an array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM