0

Good day, i have dynamically created form elements with jquery that looks like this:

<label for="fname" class="fname_label col-sm-2 control-label">First Name</label>
<div class="col-sm-4">
    <input type="text" class="fname_input form-control" id="fname" placeholder="First Name" name="firstnames">
</div>

<label for="uemail" class="uemail_label col-sm-2 control-label">Email</label>
<div class="col-sm-4">
    <input type="text" class="uemail_input form-control" id="uemail" placeholder="Email" name="emailaddresses">

A user can create multiple elements like this with same name and ids. I mean if a user should click on add more, the same elements are created with the same name and id with jquery. A user can create multiple elements say 10 or more. My question is how can i post or insert the values of the dynamically create elements to the database. i am using c# in MVC. Thank You.

8
  • 1
    Duplicate id attributes are invalid html. And to bind to a collection, your inputs need collection indexers. Refer this answer for some examples Commented Apr 2, 2017 at 13:00
  • Start by reading the specification to understand why this is not a valid scenario w3.org/TR/2011/WD-html5-20110525/elements.html#the-id-attribute This covers the name attribute w3.org/TR/html401/interact/forms.html#h-17.2 Commented Apr 2, 2017 at 13:12
  • Note that what you describe are called "successful controls" in the specifications as well: w3.org/TR/html401/interact/forms.html#successful-controls Commented Apr 2, 2017 at 13:18
  • thank you @MarkSchultheiss, so is it not possible to post a form that has multiple controls with the same name? Commented Apr 2, 2017 at 13:25
  • Some elements WILL have the same name such as input type radio. Text type for your example will pair the name with the value on the form submission - thus the name will be unique within a FORM - as noted in the form documentation for a "successful" control. Either way, duplicate ID's are invalid within the document (not just the form) and will produce unpredictable results. Commented Apr 2, 2017 at 14:36

1 Answer 1

1

Had a bit of time and put this together. I created a JavaScript namespace to hold my functions, data etc; kept the jQuery part separate for the event (submit and add rows) management. You could easily add capability to delete new entry groups (row) as well, just need ONE to stay as I used .clone() to get that new row.

Sample markup using some bootstrap stuff (not required for the functional part). Note I used jQuery for the ajax stuff, you would not have to but it made the sample a bit smaller perhaps.

<div class="container">
  <form id="myform">
    <div class="inputs-holder">
      <fieldset class="entry-group">
        <legend class="col-form-legend col-xm-2">
          one input
        </legend>
        <div class="form-group row">
          <label class="col-xs-2 col-form-label col-form-label-sm">Name</label>
          <div class="col-xs-7">
            <input required="true" class="form-control form-control-xs name-field" type="text" />
          </div>
        </div>
        <div class="form-group row">
          <label class="col-xs-2 col-form-label col-form-label-sm">Email</label>
          <div class="col-xs-7">
            <input required="true" class="form-control form-control-xs email-field" type="email" placeholder="enter email" value="[email protected]" />
          </div>
        </div>
      </fieldset>
    </div>
    <div class="form-group row">
      <div class="offset-xs-2 col-xs-5">
        <button id="submitme" type="submit" class="btn btn-primary btn-xs">Submit Me</button>
      </div>
      <div class="offset-xs-2 col-xs-5">
        <button id="addnewgroup" type="button" class="btn btn-xs">Add new group</button>
      </div>
    </div>
  </form>
</div>
<div id="results">
  Entries
</div>

Some script to process and push data via ajax to server:

/* Latest compiled and minified JavaScript included as External Resource */

var myApp = myApp || {};
myApp.arrayObj = {
  // some stuff clipped out not used here...
  // use to lookup duplicates
  lookup: function(myArray, searchTerm, property, firstOnly) {
    var found = [];
    var i = myArray.length;
    while (i--) {
      if (myArray[i][property] === searchTerm) {
        found.push(myArray[i]);
        if (firstOnly) break; //if only the first 
      }
    }
    return found;
  },
  // could be used to validate duplicates for example
  lookupAll: function(myArray, property, searchTerm) {
    return this.lookup(myArray, searchTerm, property, false);
  }
};
myApp.data = {
  entries: [],
  saveUrl: "/Home/SaveEmails" this COULD be from server/MVC
};
myApp.func = {
  addEmailRow: function(myArray, item, allowdups, uniquekey) {
    // matches the  POCO object class names
    var entry = {
      "name": item.name,
      "email": item.email
    };
    if (allowdups || (!allowdups && !myApp.arrayObj.lookup(myArray, entry[uniquekey], uniquekey, true).length)) {
      myArray.push(entry);
    } else if (allowdups && myApp.arrayObj.lookup(myArray, entry[uniquekey], uniquekey, true).length) {
      myApp.data.entries[uniquekey] = item[uniquekey];
    } else if (allowdups && !myApp.arrayObj.lookup(myArray, entry[uniquekey], uniquekey, true).length) {
      myArray.push(entry);
    }
  },
  // just something to show what is entered/being submitted
  showEntries: function(list) {
    $.each(list, function(index, value) {
      $('#results').append("<div>" + value.name + " " + value.email + "</div>");
    });
  },
  // the important part
  saveEntries: function(list) {
    var entries = JSON.stringify({
      'Entries': list
    });

    $.ajax({
        contentType: 'application/json;',
        dataType: 'json',
        type: 'POST',
        url: myApp.data.saveUrl,
        data: entries
      }).done(function() {
        $('#results').html('"SaveEmails()" successfully called.');
      })
      .fail(function(response) {
        $('#results').html(response);
      });
  }
};
$(document).ready(function() {
  // add new "group" row
  $('#addnewgroup').on('click', function() {
    var holder = $('.inputs-holder');
    // clone that first row
    var newRow = holder.find('.entry-group').eq(0).clone();
    // clear any values entered and append it
    newRow.find('input').val("");
    newRow.appendTo(holder);
  });
  // a bit verbose for clarity here
  $('#myform').on('submit', function(e) {
    e.preventDefault();
    e.stopPropagation();
    // clear entries
    myApp.data.entries = [];
    var allowdups = false,
      uniquekey = "name";
    var holder = $('.inputs-holder');
    // get entries
    holder.find('.entry-group').each(function() {
      var email = $(this).find('.email-field').val();
      var name = $(this).find('.name-field').val();
      var item = {
        "email": email,
        "name": name
      };
      myApp.func.addEmailRow(myApp.data.entries, item, allowdups, uniquekey);
    });
    $('#results').html("<div>Results:</div>");
    myApp.func.showEntries(myApp.data.entries);
    myApp.func.saveEntries(myApp.data.entries);

    // supress default submit form
    return false;
  });
});

Now the server side:

/* MVC for this: */
// POCO object: - reference this whereever you put it.
public class EmailEntry
{
    public String name { get; set; }
    public String email { get; set; }
}

// controller/ method: used IEnumerable instead of List as simpler
public class HomeController : Controller
{
   [HttpPost]
    public void SaveEmails(IEnumerable<EmailEntry> entries)
    {
        // do stuff with email entries here...validate/save for example
    }
}

ALL this is untested and my contain small errors but I believe it to be pretty bug free.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.