skip to Main Content

I am looping through FormData.entries() when performing form validation. However the entries do not include a radio button. The following is how I initialize my loop, and I have added the logging:

for (let [fieldName, val] of formData.entries()) {
  console.log(fieldName);

This results in the following being emitted to console:

  • name
  • email
  • property
  • deliveryAddr
  • startDate
  • duration
  • other

I expected deliveryCity to come right after deliveryAddr. Below is the block of code that contains them both. Please note various classes are from Bulma. My first thought was that I had not specified the value attribute for the radio buttons, but adding those did not result in deliveryCity being added to the FormData.entries() Thanks for having a look.

<div class="mt-2 is-hidden abc-contact-form-delivery-required-fields">
  <div class="field">
    <label class="label is-size-4">
      <span class="mr-1 has-text-primary-dark">Delivery Street Address</span>
      <span class="has-text-danger">*</span>
    </label>
    <div class="control has-icons-left has-icons-right abc-featured-property-label">
      <input class="input" type="text" class="abc-contact-form-field-delivery-addr" name="deliveryAddr" placeholder="Your Beach Home Address">
      <span class="icon is-small is-left">
        <i class="fas fa-road"></i>
      </span>
    </div>
  </div>
  <div>
    <label class="label is-size-4">
      <span class="mr-1 has-text-primary-dark">Delivery City</span>
      <span class="has-text-danger">*</span>
    </label>
    <div class="mb-3 abc-featured-property-label">Sorry we do not deliver to Fort Morgan</div>
    <div class="field abc-featured-property-label">
      <div class="control">
        <label class="radio is-size-5">
          <input type="radio" name="delivery-city" value="Orange Beach" class="abc-contact-form-field-delivery-city">
          Orange Beach
        </label>
        <label class="radio is-size-5">
          <input type="radio" name="delivery-city" value="Gulf Shores" class="abc-contact-form-field-delivery-city">
          Gulf Shores
        </label>
      </div>
    </div>
  </div>
</div>

2

Answers


  1. Seems that’s how the FormData constructor behaves. When you have your radios not selected that basically means their value is undefined. In JS lingo undefined kinda means no defined property. So the FormData skips inputs with undefined values. When you select the radio input it becomes available in the formData.
    As you can see the default value of an empty text box is an empty string "" so it’s not undefined and the text box is added to the formData. Anyway I don’t recommend to have not pre-filled radio buttons in a form. Not good for UX. Provide some undefined selected radio input at least. Or use a select box as an alternative.

    let counter = 0;
    
    document.querySelector('form').addEventListener('submit', e => {
    
      e.preventDefault();
      counter++;
      
      const formData = new FormData(e.target, e.target.querySelector('button'));
      
      for (let [fieldName, val] of formData.entries()) {
        console.log(counter, ':', fieldName, JSON.stringify(val));
      }
    
    });
    <form>
    <div class="mt-2 is-hidden abc-contact-form-delivery-required-fields">
      <div class="field">
        <label class="label is-size-4">
          <span class="mr-1 has-text-primary-dark">Delivery Street Address</span>
          <span class="has-text-danger">*</span>
        </label>
        <div class="control has-icons-left has-icons-right abc-featured-property-label">
          <input class="input" type="text" class="abc-contact-form-field-delivery-addr" name="deliveryAddr" placeholder="Your Beach Home Address">
          <span class="icon is-small is-left">
            <i class="fas fa-road"></i>
          </span>
        </div>
      </div>
      <div>
        <label class="label is-size-4">
          <span class="mr-1 has-text-primary-dark">Delivery City</span>
          <span class="has-text-danger">*</span>
        </label>
        <div class="mb-3 abc-featured-property-label">Sorry we do not deliver to Fort Morgan</div>
        <div class="field abc-featured-property-label">
          <div class="control">
            <label class="radio is-size-5">
              <input type="radio" name="delivery-city" value="Orange Beach" class="abc-contact-form-field-delivery-city">
              Orange Beach
            </label>
            <label class="radio is-size-5">
              <input type="radio" name="delivery-city" value="Gulf Shores" class="abc-contact-form-field-delivery-city">
              Gulf Shores
            </label>
          </div>
        </div>
      </div>
    </div>
    <button>Submit</button>
    </form>
    Login or Signup to reply.
  2. If you are validating the form I think that you should stick to the defaults as much as possible.

    • Set the required attribute in input elements
    • Use the build in event listeners

    So, here is an example. Read the comments to see what the different event listeners do.

    const beaches = ['Orange Beach', 'Gulf Shores', 'Perdido Key', 'Fort McRee', 'Langdon Beach', 'Pensacola Beach', 'Pensacola Dog Beach', 'Opal Beach', 'Navarre Beach'];
    
    // Specific input to the deliveryAddr input
    document.forms.form01.deliveryAddr.addEventListener('input', e => {
      // fetch array of beaches if needed
      
      // if beach is in the array set the pattern
      // to be the current value and thereby the input to be valid.
      if (beaches.find(beach => beach == e.target.value)) {
        e.target.setAttribute('pattern', e.target.value);
      }
    });
    
    // Any input to any input in the form
    document.forms.form01.addEventListener('input', e => {
      // if some input, test if input is valid and if so
      // remove the class 'invalid' being there or not on the div.control
      if (e.target.validity.valid) {
        e.target.closest('div.control').classList.remove('invalid');
      }
    });
    
    // If submit button if clicked or the function checkValidity()
    // on the form is called this eventlistener will trigger.
    // This overrides the default message by calling e.preventDefault();
    document.forms.form01.addEventListener('invalid', e => {
      e.preventDefault();
      // when something is invalid (input element being e.target)
      // set the div.control to be invalid
      e.target.closest('div.control').classList.add('invalid');
    }, true);
    
    // If form is valide and the form is submitting
    document.forms.form01.addEventListener('submit', e => {
      e.preventDefault();
      console.log('form submitting...');
    }, false);
    input:invalid {
      border: thin solid red;
    }
    
    input:valid {
      border: thin solid green;
    }
    
    div.control span {
      display: none;
      background-color: orange;
    }
    
    div.control.invalid span {
      display: inline;
    }
    <form name="form01">
      <div class="mt-2 is-hidden abc-contact-form-delivery-required-fields">
        <div class="field">
          <label class="label is-size-4">
          <span class="mr-1 has-text-primary-dark">Delivery Street Address</span>
          <span class="has-text-danger">*</span>
        </label>
          <div class="control has-icons-left has-icons-right abc-featured-property-label">
            <input class="input" type="text" class="abc-contact-form-field-delivery-addr" name="deliveryAddr" placeholder="Your Beach Home Address" pattern="abc" required>
            <span>Beach not valid</span>
            <span class="icon is-small is-left">
              <i class="fas fa-road"></i>
            </span>
          </div>
        </div>
        <div>
          <label class="label is-size-4">
          <span class="mr-1 has-text-primary-dark">Delivery City</span>
          <span class="has-text-danger">*</span>
        </label>
          <div class="mb-3 abc-featured-property-label">Sorry we do not deliver to Fort Morgan</div>
          <div class="field abc-featured-property-label">
            <div class="control">  
              <label class="radio is-size-5"><input type="radio" name="delivery-city" value="Orange Beach" class="abc-contact-form-field-delivery-city" required>Orange Beach</label>
              <label class="radio is-size-5"><input type="radio" name="delivery-city" value="Gulf Shores" class="abc-contact-form-field-delivery-city">Gulf Shores</label>
              <span>Beach not selected</span>
            </div>
          </div>
        </div>
      </div>
      <button type="submit">Submit</button>
    </form>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search