开发者

Best Practice: Access form elements by HTML id or name attribute?

开发者 https://www.devze.com 2022-12-22 23:27 出处:网络
As any seasoned JavaScript developer knows, there are many (too many) ways to do the same thing.For example, say you have a text field as follows:

As any seasoned JavaScript developer knows, there are many (too many) ways to do the same thing. For example, say you have a text field as follows:

<form 开发者_StackOverflow社区name="myForm">  
    <input type="text" name="foo" id="foo" />

There are many way to access this in JavaScript:

[1]  document.forms[0].elements[0];
[2]  document.myForm.foo;
[3]  document.getElementById('foo');
[4]  document.getElementById('myForm').foo;
     ... and so on ...

Methods [1] and [3] are well documented in the Mozilla Gecko documentation, but neither are ideal. [1] is just too general to be useful and [3] requires both an id and a name (assuming you will be posting the data to a server side language). Ideally, it would be best to have only an id attribute or a name attribute (having both is somewhat redundant, especially if the id isn't necessary for any css, and increases the likelihood of typos, etc).

[2] seems to be the most intuitive and it seems to be widely used, but I haven't seen it referenced in the Gecko documentation and I'm worried about both forwards compatibility and cross browser compatiblity (and of course I want to be as standards compliant as possible).

So what's best practice here? Can anyone point to something in the DOM documentation or W3C specification that could resolve this?

Note I am specifically interested in a non-library solution (jQuery/Prototype).


Give your form an id only, and your input a name only:

<form id="myform">
  <input type="text" name="foo">

Then the most standards-compliant and least problematic way to access your input element is via:

document.getElementById("myform").elements["foo"]

using .elements["foo"] instead of just .foo is preferable because the latter might return a property of the form named "foo" rather than a HTML element!


[1] document.forms[0].elements[0];

"No-omg-never!" comes to mind when I see this method of element access. The problem with this is that it assumes that the DOM is a normal data structure (e.g.: an array) wherein the element order is static, consistent or reliable in anyway. We know that 99.9999% of the time, that this is not the case. Reordering or input elements within the form, adding another form to the page before the form in question, or moving the form in question are all cases where this code breaks. Short story: this is very fragile. As soon as you add or move something, it's going to break.

[2] document.myForm.foo;

I'm with Sergey ILinsky on this:

  • Access arbitrary elements by referring to their id attribute: document.getElementById("myform");
  • Access named form elements by name, relative to their parent form element: document.getElementById("myform").foo;

My main issue with this method is that the name attribute is useless when applied to a form. The name is not passed to the server as part of the POST/GET and doesn't work for hash style bookmarks.

[3] document.getElementById('foo');

In my opinion, this is the most preferable method. Direct access is the most concise and clear method.

[4] document.getElementById('myForm').foo;

In my opinion, this is acceptable, but more verbose than necessary. Method #3 is preferable.


I just so happened to be watch a video from Douglas Crockford and he weighed in on this very subject. The point of interest is at -12:00. To summarize:

  • Document collections (document.anchor, document.form, etc) are obsolete and irrelevant (method 1).
  • The name attribute is used to name things, not to access them. It is for naming things like windows, input fields, and anchor tags.
  • "ID is the thing that you should use to uniquely identify an element so that you can get access to it. They (name and ID) used to be interchangeable, but they aren't anymore."

So there you have it. Semantically, this makes the most sense.


To access named elements placed in a form, it is a good practice to use the form object itself.

To access an arbitrary element in the DOM tree that may on occasion be found within a form, use getElementById and the element's id.


I much prefer a 5th method. That is
[5] Use the special JavaScript identifier this to pass the form or field object to the function from the event handler.

Specifically, for forms:

<form id="form1" name="form1" onsubmit="return validateForm(this)">

and

// The form validation function takes the form object as the input parameter
function validateForm(thisForm) {
  if (thisform.fullname.value !=...

Using this technique, the function never has to know
- the order in which forms are defined in the page,
- the form ID, nor
- the form name

Similarly, for fields:

<input type="text" name="maxWeight">
...
<input type="text" name="item1Weight" onchange="return checkWeight(this)">
<input type="text" name="item2Weight" onchange="return checkWeight(this)">

and

function checkWeight(theField) {
  if (theField.value > theField.form.maxWeight.value) {
    alert ("The weight value " + theField.value + " is larger than the limit");
    return false;
  }
return true;
}

In this case, the function never has to know the name or id of a particular weight field, though it does need to know the name of the weight limit field.


It’s not really answering your question, but just on this part:

[3] requires both an id and a name... having both is somewhat redundant

You’ll most likely need to have an id attribute on each form field anyway, so that you can associate its <label> element with it, like this:

<label for="foo">Foo:</label>
<input type="text" name="foo" id="foo" />

This is required for accessibility (i.e. if you don’t associate form labels and controls, why do you hate blind people so much?).

It is somewhat redundant, although less so when you have checkboxes/radio buttons, where several of them can share a name. Ultimately, id and name are for different purposes, even if both are often set to the same value.


This is a bit old but I want to add a thing I think is relevant.
(I meant to comment on one or 2 threads above but it seems I need reputation 50 and I have only 21 at the time I'm writing this. :) )
Just want to say that there are times when it's much better to access the elements of a form by name rather than by id. I'm not talking about the form itself. The form, OK, you can give it an id and then access it by it. But if you have a radio button in a form, it's much easier to use it as a single object (getting and setting its value) and you can only do this by name, as far as I know.

Example:

<form id="mainForm" name="mainForm">
    <input type="radio" name="R1" value="V1">choice 1<br/>
    <input type="radio" name="R1" value="V2">choice 2<br/>
    <input type="radio" name="R1" value="V3">choice 3
</form>

You can get/set the checked value of the radio button R1 as a whole by using
document.mainForm.R1.value
or
document.getElementById("mainForm").R1.value
So if you want to have a unitary style, you might want to always use this method, regardless of the type of form element. Me, I'm perfectly comfortable accessing radio buttons by name and text boxes by id.


Being old-fashioned I've always used the 'document.myform.myvar' syntax but I recently found it failed in Chrome (OK in Firefox and IE). It was an Ajax page (i.e. loaded into the innerHTML property of a div). Maybe Chrome didn't recognise the form as an element of the main document. I used getElementById (without referencing the form) instead and it worked OK.


OLD QUESTION, NEW INSIGHTS (2021)

After reading and learning from some of the excellent answers to this question, is needed to go back to basics and try to get more data how id and name are defined in their origins.

The result was simple and enlightening. I'm summarizing it below:


  • The most important fact is, by far, that id and name are so different and have so different purposes, that they are defined in separate sections of the W3/WHATWG specifications. In short:
    • id:
      • defined as part of the DOM (web document standards) specification and NOT as an HTML (markup language) thing. So, id is DOM (document), not HTML (language).
      • its purpose is directly related to the unique identification of a node in the document. Therefore, very suitable to access nodes.
      • must be unique
    • name:
      • defined as part of the HTML specifications and NOT as and DOM. Therefore, name is HTML (language), not DOM (web document).
      • its purposes is directly related to form submission - how a form is structured, its enctype, the data sent to the server (eg. via https), and so on.

  • Based on the above data and some accumulated experience as a developer, my main conclusions are:
    1. The confusion about using id or name to access an element is caused by some main factors:
      • while the very term element is clearly defined in the DOM specification, it doesn't have a very clear definition on the HTML specification - which refers to DOM, xhtml namespace, etc.
      • we, developers, don't like to dig into the technicalities of definitions (maybe I don't need to detail this assumption here), which can cause further misunderstandings.
      • as a result, the term element is widely used to refer both to a HTML tag (eg, a form) and a DOM node (despite the fact that a form is a node in the DOM, but not vice-versa.)
      • JavaScript provides a number of ways to access things in the DOM, including the ones based on its own stuff, like (getElementsByTagName, getElementsByName) which requires some behind-the-scenes actions to retrieve the actual nodes from the DOM.
      • on one hand, it makes easier for the developers to access these elements; on other hand, it hides the concepts and structures that are playing important roles in that particular context.
      • ultimately, the above factors generate confusions that lead to necessary and clever questions like the one that originates this whole thread.
    2. after having read the answers and comments, gathered data, burned some neurons by analyzing the data and making conclusions, my answer to the question is:
      • if you want to keep it strictly technical (and probably have some gain in performance), then go for id wherever is possible and makes sense - for example, it doesn't make sense to add the id everywhere; probably it doesn't make sense to use the id attribute in radio input types.
      • if you want to use the flexibility offered by JavaScript, but keeping the best from both worlds, I would suggest the solution provided by @Doin in this thread.
      • I also appreciated the Accessibility factor brought by @paul-d-waite. The same factor is explored in this answer as well.
      • keep in mind that not everything you can you should.

References:

  1. HTML - name
  2. HTML - element
  3. DOM - id
  4. DOM - element
  5. HTML - Living Standard — Last Updated 5 November 2021
  6. DOM - Living Standard — Last Updated 18 October 2021

It's also worth it to take a look at The form element


Other references in Stackoverflow:

was the name attribute really needed in html?

Difference between id and name attributes in HTML


Bonus: Short and cool distinction between id and name, for the impatient.


Just to add to everything already said, you may access the inputs either with the name or id using preferably the elements property of the Object form, because without it you may get a property of the form named "foo" rather than an HTML element. And according to @Paul D. Waite it's perfectly ok to have both name and id.

var myForm = document.getElementById("myform")
console.log(myForm.foo.value) // hey
console.log(myForm.foo2.value) // hey
//preferable
console.log(myForm.elements.foo.value) // hey
console.log(myForm.elements.foo2.value) // hey
<form id="myform">
  <input type="text" name="foo" id="foo2" value="hey">
</form>

According to MDN on the HTMLFormElement.elements page

The HTMLFormElement property elements returns an HTMLFormControlsCollection listing all the form controls contained in the element. Independently, you can obtain just the number of form controls using the length property.

You can access a particular form control in the returned collection by using either an index or the element's name or id.


I prefer this one:

document.forms['idOfTheForm'].nameOfTheInputFiled.value;


The name attribute works well. It provides a reference to the elements.

parent.children - Will list all elements with a name field of the parent. parent.elements - Will list only form elements such as input-text, text-area, etc.

var form = document.getElementById('form-1');
console.log(form.children.firstname)
console.log(form.elements.firstname)
console.log(form.elements.progressBar); // undefined
console.log(form.children.progressBar);
console.log(form.elements.submit); // undefined
<form id="form-1">
  <input type="text" name="firstname" />
  <input type="file" name="file" />
  <progress name="progressBar" value="20" min="0" max="100" />
  <textarea name="address"></textarea>
  <input type="submit" name="submit" />
</form>

Note: For .elements to work, the parent needs to be a <form> tag. Whereas, .children will work on any HTML-element - such as <div>, <span>, etc.


To supplement the other answers, document.myForm.foo is the so-called DOM level 0, which is the way implemented by Netscape and thus is not really an open standard even though it is supported by most browsers.


Form 2 is ok, and form 3 is also recommended.

Redundancy between name and id is caused by the need to keep compatibility. In HTML5 some elements (such as img, form, iframe and such) will lose their "name" attribute, and it's recommended to use just their id to reference them from now on :)


Check out this page: Document.getElementsByName()

document.getElementsByName('foo')[0]; // returns you element.

It has to be 'elements' and must return an array, because more than one element could have the same name.


My answer will differ on the exact question. If I want to access a certain element specifically, then will I use document.getElementById(). An example is computing the full name of a person, because it is building on multiple fields, but it is a repeatable formula.

If I want to access the element as part of a functional structure (a form), then will I use:

var frm = document.getElementById('frm_name');
for(var i = 0; i < frm.elements.length;i++){
   ..frm.elements[i]..

This is how it also works from the perspective of the business. Changes within the loop go along with functional changes in the application and are therefore meaningful. I apply it mostly for user friendly validation and preventing network calls for checking wrong data. I repeat the validation server side (and add there some more to it), but if I can help the user client side, then is that beneficial to all.

For aggregation of data (like building a pie chart based on data in the form) I use configuration documents and custom made JavaScript objects. Then is the exact meaning of the field important in relation to its context and do I use document.getElementById().


Because the case [2] document.myForm.foo is a dialect from Internet Explorer.

So instead of it, I prefer document.forms.myForm.elements.foo or document.forms["myForm"].elements["foo"].

0

精彩评论

暂无评论...
验证码 换一张
取 消