0

I am working on a form that the user (parent) can add multiple kids' information.
My current code is something like below:

(() => {
  let currentCount = 0
  const submitButton = document.querySelector('#submitForm')

  document.querySelector('#addMoreFields').addEventListener('click', (event) => {
    event.preventDefault()

    // find and clone the template content
    const theForm = document.querySelector('#theForm')
    const template = theForm.getElementsByTagName('template')[0]
    const clone = template.content.cloneNode(true)

    // if the submitButton is hidden, show it
    if (submitButton.offsetParent === null) {
      submitButton.removeAttribute('style')
    }

    // add class to set and name on input fields
    clone.querySelector('.set').classList.add(`set-${currentCount}`)
    clone.querySelector('.first_name').setAttribute('name', `firstName[${currentCount}]`)
    clone.querySelector('.middle_name').setAttribute('name', `middleName[${currentCount}]`)
    clone.querySelector('.last_name').setAttribute('name', `lastName[${currentCount}]`)
    theForm.append(clone)

    currentCount++
  })
  
  submitButton.addEventListener('click', (event) => {
    event.preventDefault()
    
    const theArray = []
    // create an object and push to the array
  })
})()
.set {
  margin: 5px;
  padding: 5px;
  outline: 1px solid #ccc;
}
<form id="theForm">
  <template>
    <div class="set">
      <input class="first_name" placeholder="first name" />
      <input class="middle_name" placeholder="middle name" />
      <input class="last_name" placeholder="last name" />
    </div>
  </template>
  <button id="addMoreFields">add</button>
  <button id="submitForm" style="display: none;">submit</button>
</form>

My issue is, how can I create an array of objects to be sent to the back-end.
We are only using vanilla javascript so jQuery is not an option 😞

1 Answer 1

1

You can reduce all div.set using a reducer also for the input-fields within every div.set. Like:

(() => {
  let currentCount = 0
  const submitButton = document.querySelector('#submitForm')
  // reducer for inputs within div.set
  const inputs2ObjectReducer = (acc, inp) => ( { ...acc, [inp.className]: inp.value } );
    
  document.querySelector('#addMoreFields').addEventListener('click', (event) => {
    event.preventDefault();

    // find and clone the template content
    const theForm = document.querySelector('#theForm');
    const template = theForm.getElementsByTagName('template')[0];
    const clone = template.content.cloneNode(true);

    // if the submitButton is hidden, show it
    if (submitButton.offsetParent === null) {
      submitButton.removeAttribute('style');
    }

    // add class to set and name on input fields
    clone.querySelector('.set').classList.add(`set-${currentCount}`);
    clone.querySelector('.first_name').setAttribute('name', `firstName[${currentCount}]`);
    clone.querySelector('.middle_name').setAttribute('name', `middleName[${currentCount}]`);
    clone.querySelector('.last_name').setAttribute('name', `lastName[${currentCount}]`);
    theForm.append(clone);

    currentCount++;
  })

  submitButton.addEventListener('click', (event) => {
    event.preventDefault();
    
    // Reduce all div.set to array of objects
    const theArray = [...document.querySelectorAll(".set")]
      .reduce( (acc, val) =>
        [...acc, 
        [...val.querySelectorAll("input")]
          .reduce(inputs2ObjectReducer, {})], [] );
        
    console.log(theArray);
  })
})()
.set {
  margin: 5px;
  padding: 5px;
  outline: 1px solid #ccc;
}
<form id="theForm">
  <template>
    <div class="set">
      <input class="first_name" placeholder="first name" />
      <input class="middle_name" placeholder="middle name" />
      <input class="last_name" placeholder="last name" />
    </div>
  </template>
  <button id="addMoreFields">add</button>
  <button id="submitForm" style="display: none;">submit</button>
</form>

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.