2

So, let's say I have an HTML form like this:

<form id="myForm">
    <input type="text" name="dummy">
    <input type="text" name="people[0][first_name]" value="John">
    <input type="text" name="people[0][last_name]" value="Doe">
    <input type="text" name="people[1][first_name]" value="Jane">
    <input type="text" name="people[1][last_name]" value="Smith">
</form>

And I want to get a JavaScript array that matches the values of real. For example:

// If there was a sweet function for this...
var people = getFormDataByInputName( 'people' );

// Value of `people` is...
// [
//    {
//        'first_name' : 'John',
//        'last_name'  : 'Doe'
//    },
//    {
//        'first_name' : 'Jane',
//        'last_name'  : 'Smith'
//    }
// ]

Is there any easy way of doing that for just a specific form item (in this case, people)? Or would I have to serialize the entire form an then just extract the element I want?

I also thought of potentially using the following approach:

var formData = new FormData( document.querySelector( '#myForm' ) );
var people = formData.get( 'people' );

But that doesn't appear to work; people is just null after that.

1
  • So people is an array of objects and you want an html form to push a new object in people ? Commented Mar 3, 2018 at 1:34

4 Answers 4

2

You could do this with plain js using reduce method and return each person is one object.

const form = document.querySelectorAll('#myForm input');
const data = [...form].reduce(function(r, e) {
  const [i, prop] = e.name.split(/\[(.*?)\]/g).slice(1).filter(Boolean)
  if (!r[i]) r[i] = {}
  r[i][prop] = e.value
  return r;
}, [])

console.log(data)
<form id="myForm">
  <input type="text" name="dummy">
  <input type="text" name="people[0][first_name]" value="John">
  <input type="text" name="people[0][last_name]" value="Doe">
  <input type="text" name="people[1][first_name]" value="Jane">
  <input type="text" name="people[1][last_name]" value="Smith">
</form>

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

Comments

0

function getObject(name, key) {
  if(key.includes(name)) {
    var splitStr = key.split(/\[|\]/g);
    return {
      index: splitStr[1],
      key: splitStr[3],
    }
  }
  return null;
}

function getFormDataByInputName(name) {
 var formData = new FormData( document.querySelector('#myForm'));
 var results = [];
 for (var key of formData.keys()) {
   var obj = getObject(name, key);
   if (obj) {
      if (results[obj.index]) results[obj.index][obj.key] = formData.get(key);
      else results[obj.index] = { [obj.key]: formData.get(key) };
   }
 }
 return results;
}


var people = getFormDataByInputName('people');

console.log(people);
<form id="myForm">
    <input type="text" name="dummy">
    <input type="text" name="people[0][first_name]" value="John">
    <input type="text" name="people[0][last_name]" value="Doe">
    <input type="text" name="people[1][first_name]" value="Jane">
    <input type="text" name="people[1][last_name]" value="Smith">
</form>

Comments

0

Your code won't work because to HTML/JS name is just a string that it sends to the server when the form is submitted (the name in the name/value pairs). You might think it is arrays, but HTML/JS doesn't.

So no one-liner to get the job done. Try this: In your HTML, add <div class="name"> ...

(UPDATE: thanks for the idea, @Nenad, I've never tried one of these snippets)

var people = [];
$('.name').each(function() {
    people.push({
        first_name: $('input:nth-child(1)', this).val(),
        last_name: $('input:nth-child(2)', this).val()
    });
});
console.log(people);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<form id="myForm">
  <input type="text" name="dummy">
  <div class="name">
    <input type="text" value="John">
    <input type="text" value="Doe">
  </div>
  <div class="name">
    <input type="text" value="Jane">
    <input type="text" value="Smith">
  </div>
</form>

Comments

0

Use CSS attribute prefix selector, such as

form.querySelectorAll('[name^="people[]"]')

Example

const form = document.querySelector('#myForm');
const MAX_PEOPLES = 2;
const list = [];
for (i = 0; i <= MAX_PEOPLES; i++) {
  const eles = form.querySelectorAll(`[name^="people[${i}]`);
  if (eles.length < 2)
    continue;

  list.push({
    first_name: eles[0].value,
    last_name: eles[1].value
  });
}

console.log(list)
<form id="myForm">
  <input type="text" name="dummy">
  <input type="text" name="people[0][first_name]" value="John">
  <input type="text" name="people[0][last_name]" value="Doe">
  <input type="text" name="people[1][first_name]" value="Jane">
  <input type="text" name="people[1][last_name]" value="Smith">
</form>

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.