3 minute read
June 29, 2017

Make an input required only if visible

Sometimes you want to set an input to required, but that field it isn't displayed unless a condition is met. You might think it is as simple as browsers recognising the input's parent node is set to display: none, but you'd be wrong. I ran into this problem myself while working on Bikmo's new account application.

When a customer wants to change the address where their bikes are stored, we only need their postcode. We then use that to make a call to a postcode API and return all the addresses associated with that postcode. But what if their address isn't listed? Well we have a fallback form that they can use to fill in their address manually.

Within that form, there are three fields that are required. The first line of their address, their post town and their county. Now if every input was required, it would be simple to just strip all of them of their required property. You would then add them back when the field is set to visible. However, because some fields are required and others aren't, we can't use that approach.

Enter the data-attribute property

In order to target specific fields, we used HTML5's data property. In this case, we created the data-required property, which was set to either true or false. If the field was required, we set it to true. If not, it was set to false. This replaced the actual required property.

We then wrote some JavaScript that watches the address dropdown for a change event. If the option manual is selected, then it toggles the visibility of the input fields.

We also assigned all inputs with the targeted data property set to true to an object. This object is ran through an if statement on the same change event. If the option selected is manual, it adds the required property to all inputs that match the data property.

The else condition watches the change event and if the option isn't manual, then it sets all matching inputs to required="false". It also hides the containing div.

Code example

Note, that while we set the value of the data property to true, it returns as 1 for true and null for false

const dropdown = $('#dropdown');
const container = $('#container-div');
const requiredInputs = $('input[data-required="1"]');

container.change(function(){
  if($(this).val() == 'manual') {
    container.addClass('visible');
    if (requiredInputs) {
      requiredInputs.prop('required', 'true');
    }
  } else {
    container.removeClass('visible');
    if (requiredInputs) {
      requiredInputs.prop('required', 'false');
    }
  }
});

This can almost certainly be refactored and improved, but for the time being it works. Hopefully if you get stuck on the same issue, it will give you some ideas.