1

Often I'm creating some kind of form on a website, and I have a <label> and a <input> which should be linked together.

The standard way to do this is by setting the 'for' attribute on the <label> to match the 'id attribute on the <input>

<label for="city-input">City</label>
<input id="city-input" type="text" />

This of course relies on having a unique ID for every <input> element on the page.

I frequently find myself in the situation where I have to create the form dynamically and the exact contents of the rest of the page are unknown or out of my control. So I can't just assign an id like 'city-input' in case it clashes with something else on the page. I end up creating random strings to use as ids:

var label = document.createElement('label');
label.innerHTML = 'City';
var input = document.createElement('input');
input.type = 'text';
// create a random string as the id
var id = Math.random().toString(36).substring(2);
input.id = id;
label.htmlFor = id;

This method works, but I hate it. I've got my HTMLInputElement instance and my HTMLLabelElement instance. I want to link them together. But I have to pointlessly create a random string to use as an intermediary. Then when someone clicks the <label> the browser has to pointlessly look up the string id to find the <input> element. It's so inelegant.

Is there any way to directly associate the HTMLLabelElement with the HTMLInputElement? Or some other better method?

(I know you can avoid the id by putting the <input> inside the <label> but this often isn't possible because of the way the page will be styled or various other reasons).

4
  • “It's so inelegant” - no, inventing another way than the one specified, just to please your specific requirement, that would be inelegant. The way to have a label implicitly associated with an input field is the one you don’t want, so you have to use the explicit way, and that is via id/for. “Then [...] the browser has to pointlessly look up the string id ” - that’s what it is already heavily optimized for. Commented Feb 9, 2018 at 9:28
  • I don't think my requirement is very specific. Most websites are made from smaller reusable components. Whenever you're writing some kind of reusable HTML component, you have the problem of not knowing what else might be on the page, and what element ids might exist outside your code. Commented Feb 9, 2018 at 11:34
  • Ok, fair enough. But those arguments were probably not really applicable at the time this was specified ... So you will have to use what exists. stackoverflow.com/q/20060931/1427878 lists some ways to create “unique ids”, and common frameworks often provide such functionality as well, such as f.e. jQuery UI with api.jqueryui.com/uniqueId Commented Feb 9, 2018 at 11:40
  • If the answer is "No, there's no other way", then fine, that's the answer, and I'll carry on using string ids. I thought it's worth asking the question, in case there was another technique that I didn't know about. Commented Feb 9, 2018 at 12:37

2 Answers 2

0

You can avoid the random number by just using an incrementing counter as the unique id of the form elements. I have created a codepen here that shows the addition of a random number of form elements every time the refresh button is clicked. Each element has it's own label and input, both linked by the generation of a unique incrementing id. All of which can be referenced individually. Clicking on the label will automatically highlight the linked form input.

Just for clarity I have used the following format for the linking ids:

  var id="_" + counter +"_"+i;
  var labelId = "labelForCity_" + counter +"_"+i;
  var inputId = "city_" + counter +"_"+i;

Then the label is linked to the input by

label.htmlFor = inputId;

Each time the refresh button is clicked (simulating a dynamic number of additional fields being added to your form) the counter variable is incremented which is used in the id. The id is shown in brackets beside the input field.

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

Comments

-1

If your label and input are residing side by side always(they should be), then you can write a method to provide focus to next input when you click on the label. Example code, you can modify it according to your need:

HTML -

<label>something</label>
<input />

Javascript -

var a = document.getElementsByTagName('label')[0];
a.addEventListener('click', function(e){
 e.target.nextElementSibling.focus();
});

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.