ベストプラクティス:HTML IDまたは名前属性でフォーム要素にアクセスしますか?


136

熟練したJavaScript開発者なら誰でも知っているように、同じことを行う方法はたくさんあります(多すぎます)。たとえば、次のようなテキストフィールドがあるとします。

<form name="myForm">  
    <input type="text" name="foo" id="foo" />

JavaScriptでこれにアクセスするには多くの方法があります。

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

メソッド[1]と[3]はMozilla Geckoのドキュメントに詳しく記載されていますが、どちらも理想的ではありません。[1]はあまりにも一般的すぎて役に立たず、[3]はIDと名前の両方を必要とします(サーバー側の言語にデータを投稿する場合)。理想的には、id属性またはname属性のみを持つことをお勧めします(特に、CSSにidが不要であり、タイプミスの可能性が高まる場合など、両方を持つことは多少冗長です)。

[2]が最も直感的であり、広く使用されているようですが、Geckoのドキュメントで参照されていることはありません。また、上位互換性とクロスブラウザー互換性の両方が心配です(もちろん、可能な限り標準に準拠しています)。

ここでのベストプラクティスは何ですか?誰でもこれを解決できるDOMドキュメントまたはW3C仕様で何かを指すことができますか?

ライブラリ以外のソリューション(jQuery / Prototype)に特に関心があります。



4
「特に両方のcssにidが不要で、タイプミスの可能性が高まる場合は、どちらも冗長です」-ラベルを効果的に使用するには、IDが必要です。CSSだけではありません。

Webページに複数のフォームがあり、ID属性が衝突する場合があります。
Calmarius 14年

回答:


96

フォームにIDのみを指定し、入力に名前のみを指定します。

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

次に、入力要素にアクセスするための最も標準に準拠し、問題の少ない方法は次のとおりです。

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

後者はHTML要素ではなく「foo」という名前のフォームのプロパティを返す可能性があるため、.elements["foo"]単にで.fooはなく使用することをお勧めします。


1
@カール...何を達成しようとしているの?JSをHTMLにインライン化するのはかなり洗練されていない(そして、コードの周りにラッパー関数が作成されるため、多くの場合非効率的です)という事実は別として、常に falseを返すという事実は、フォームが送信されないことを意味します。したがって、フォームが送信されることを意図していない場合(おそらく、JSコードによって完全に使用されている場合)、またはmyFunc(this)がAJAXを介してフォームを送信しない限り(そして、AJAXの場合にフォールバックとして通常の送信を行う必要はありません)どういうわけか失敗します)、...それからあなたは間違いを犯しました。
Doin

1
通常、有効なフォームデータのみを送信するには、次のようにします myform.onsubmit = validateForm;(myformはフォーム要素を参照する変数であり、validateFormは検証関数の名前です...しかし、本当に本当にしたいです)。重要な点は、フォームが無効な場合は常にfalsevalidateForm()を返し、問題のあるフィールドをユーザーに示す必要があることです。フォームデータが正しく検証されるとtrueが返され、送信アクションを続行できるようになります。
Doin

2
フォームフィールドでIDを使用しない別の理由があります。同じページの同じフォームの複数のインスタンスが必要な場合。
コリアンダー2017年

1
、あまりにも動作しますジョアン@ 提供「fooが」JavaScriptのプロパティ名として有効です。(そうではないかもしれません-HTML5はname属性の値にほとんど制限を課しません。そのため、たとえば<select name="a+b"><input type="text" name="...2">、または。これは、javascript .propertyName表記を使用して参照することはできません)。明示的な[]表記では、式から構築された名前も使用できますmyCheckBox = document.getElementById("myform").elements["CHK"+i]。さらに、文体的には、[]の方が優れていると思います。これにより、これらがJavaScriptオブジェクトのプロパティだけではないことが明確になります。YMMV。
Doin

1
リンティングに関しては、リンティングはスタイルガイドのみであり、リンティングの「エラー」はJavaScriptが無効または正しくないことを意味するものではないことに注意してください。ただし、この特定のケースでは、リンティングルールが言っているのは「JavaScriptオブジェクトプロパティを参照するときはドット表記を優先する」です。それは良い考えであり、私は一般的にそれをお勧めします。 しかしリンターがこれを実現していませんが、elements通常のJSオブジェクトではなく、elements.fooまたはelements["foo"]実際にelements.namedItem(「foo」という)に変換なっています。つまり、JSのプロパティを参照せずに、DOM定義の関数を呼び出しているのです。
Doin

34

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

この要素アクセスの方法を見ると、「no-omg-never!」が思い浮かびます。これの問題は、DOMが要素の順序が静的、一貫性、または信頼性のある通常のデータ構造(例:配列)であると想定していることです。99.9999%の確率で、そうではないことがわかっています。このコードが壊れるのinputは、フォーム内の要素の並べ替えform、問題のフォームの前のページへの別の要素の追加、または問題のフォームの移動です。短編:これは非常に壊れやすいものです。何かを追加または移動するとすぐに壊れます。

[2] document.myForm.foo;

私はこれについてサーゲイILinskyと一緒にいます:

  • id属性を参照して任意の要素にアクセスします。document.getElementById("myform");
  • 親フォーム要素を基準にして、名前で名前付きフォーム要素にアクセスします。 document.getElementById("myform").foo;

このメソッドの私の主な問題はname、フォームに適用すると属性が役に立たなくなることです。この名前はPOST / GETの一部としてサーバーに渡されず、ハッシュスタイルのブックマークでは機能しません。

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

私の意見では、これが最も望ましい方法です。直接アクセスは、最も簡潔で明確な方法です。

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

私の意見では、これは受け入れられますが、必要以上に冗長です。方法#3が推奨されます。


私はたまたま見ていました ダグラス・クロックフォードからビデオをそして彼はこのまさに主題について重くしました。関心のあるポイントは-12:00です。要約する:

  • ドキュメントコレクション(document.anchor、document.formなど)は廃止され、無関係です(方法1)。
  • name属性は、それらにアクセスしないように、物事に名前を付けるために使用されます。ウィンドウ、入力フィールド、アンカータグなどに名前を付けるためのものです。
  • 「IDは、要素にアクセスできるように要素を一意に識別するために使用する必要があるものです。以前はそれらを交換可能でした(名前とID)が、もはや交換可能ではありません。」

だからあなたはそれを持っています。意味的に、これは最も理にかなっています。


2
これは単なるハックですか?document.getElementById( "myform")。foo; DOMをかなり調べた後、なぜこれが機能するのかは不明です。私の推測では、フォームオブジェクトはhtml name属性でインデックス付けされたその子要素の配列でもあります...
seth

1
また、「名前はPOST / GETの一部としてサーバーに渡されず、ハッシュスタイルのブックマークでは機能しません」とも述べています。これは正確にサーバーに渡されるものではありませんか?PHPを使用している場合、それは$ _POSTグローバルのインデックスであるname属性です。
セス

2
@Justin、それはサーバーに渡されるname属性です。
Anurag

2
@seth古いDOM仕様はなぜdocument.aForm.foo機能するかについて非常にあいまいに見えますが、HTML5仕様はのインターフェースを明確に定義しHTMLFormElementているようcaller getter any namedItem(in DOMString name);です。whatwg.org/specs/web-apps/current-work/multipage/…の
Anurag

1
@両方とも:「...フォームに適用すると、名前属性は役に立たない...」inputまたはの名前属性のことではなくselect、の名前属性のことformです。aの名前属性はサーバーに渡されform ません
ジャスティンジョンソン

14

フォームに配置された名前付き要素にアクセスするには、formオブジェクト自体を使用することをお勧めします。

フォーム内で時々見つかるDOMツリーの任意の要素にアクセスするにはgetElementById、および要素のを使用しますid


8
「フォームオブジェクト自体を使用する」とはどういう意味ですか?フォームオブジェクトを取得したら、特定の要素にアクセスするためにどのメソッドを使用しますか?
セス

2
つまり、N5(document.getElementById( 'myForm')。elements.foo)を使用して名前付きアイテムにアクセスし、N6(document.getElementById( 'myForm')。elements)を使用して要素の反復可能なコレクションにアクセスすることをお勧めします
Sergey Ilinsky

私は自分のコードのスタイルを定義しています...そして好みとしてIDに固執しています...そのようにして、要素のアクセスはページ全体で一貫しています。+言及されているその他の理由。

1
getElementIDを使用してフォームにアクセスするのはなぜ良い習慣なのですか?なぜdocument.myFormが機能しないのですか?(私はそれが機能していない状況を持っています、そして私はなぜだろうと思います)
Spundun 2013

Hey Spundun、おそらく数か月前に問題を解決した(またはおそらく手を上げた:))が、疑問に思った場合は、フォームのHTML要素に「name」属性を指定していないことが原因であると考えられます。
シェルドンR.

8

私は5番目の方法を好む。つまり、
[5]特別なJavaScript識別子thisを使用して、フォームまたはフィールドオブジェクトをイベントハンドラから関数に渡します。

具体的には、フォームの場合:

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

そして

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

この手法を使用すると、関数は
、ページでフォームが定義されている順序
、フォームID、または
フォーム名 を知る必要はありません。

同様に、フィールドの場合:

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

そして

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;
}

この場合、重み制限フィールドの名前を知っている必要がありますが、関数は特定の重みフィールドの名前またはIDを知っている必要はありません。


根本的な原因が何であるかはわかりませんが、このアプローチでは、すべてではありませんが、一部の状況で空の文字列を返すようにしました。
ジェイコブリー

7

それは本当にあなたの質問に答えているのではなく、この部分についてです:

[3]にはIDと名前の両方が必要です...両方を持つことは多少冗長です

あなた持っている可能性が高い必要がありますidあなたがその関連付けることができるように、とにかく各フォームフィールドの属性を<label>このように、それを持つ要素を:

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

これは、アクセシビリティのために必要です(つまり、フォームのラベルとコントロールを関連付けない場合、視覚障害者をそれほど嫌うのはなぜですか?)。

これはいくらか冗長ですが、チェックボックス/ラジオボタンがあり、それらのいくつかがを共有できる場合は少なくなりますname。最終的に、idそしてname両方が、多くの場合、同じ値に設定されている場合でも、異なる目的のためのものです。


5
入力をそのラベルでラップする場合、idまたはfor属性は必要ありません。<label> Foo:<input type = "text" name = "foo" </ label>
kennebec

3
非常に真実ですが、ルックアンドフィールの点で達成できることは制限されます。
ポールD.ウェイト2010年

2
@kennebec-ラベルを要素に関連付ける場合は、常にidを使用する必要があります。古いバージョンのIE(<8?)は、forおよびid属性が一致ない場合、ラベル内の要素をラベルに関連付けませんでした。
RobG 2012

@kennebecが書いたものに加えて、IDの使用はJSグローバルを作成するため、避ける必要があります。
mikemaccana 2014年

1
@mikemaccana:以前に問題が発生するのを見たことがあります。私はあなたのIDが合理的に説明的であり、あなたのJavaScriptが賢明に名前空間を付けられていれば、問題を引き起こす可能性は低いと思います。
ポールD.ウェイト2014年

6

これは少し古いですが、関連があると思うものを追加したいと思います。
(私は上記の1つのまたは2のスレッドにコメントを意味し、私が評判50を必要と私は私がこれを書いている時点でわずか21を持っているようだ。:))
だけでは、それがアクセスするために非常に良いでしょう場合がありますことを言いたいですIDではなく名前でフォームの要素。フォーム自体について話しているのではありません。フォーム、OK、IDを指定してアクセスすることができます。しかし、フォームにラジオボタンがある場合は、それを単一のオブジェクトとして使用する方がはるかに簡単で(その値を取得および設定)、これは名前でしか行えません。

例:

<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>


document.mainForm.R1.value
または
document.getElementById( "mainForm")。R1.value を使用して、ラジオボタンR1全体のチェックされた値を取得/設定できます。
したがって、単一のスタイルが必要な場合は、フォーム要素のタイプに関係なく、常にこのメソッドを使用したい。私は、名前でラジオボタンに、IDでテキストボックスにアクセスするのが完全に快適です。


機能するのは document.forms.mainForm.R1.valueであり、これは実際に醜くて面倒なタイプの使用を避ける良い方法ですdocument.getElementById()
Kai Carver

2

古臭いので、私は常に「document.myform.myvar」構文を使用してきましたが、最近Chromeで失敗することがわかりました(FirefoxおよびIEでは問題ありません)。これはAjaxページでした(つまり、divのinnerHTMLプロパティに読み込まれました)。Chromeがフォームをメインドキュメントの要素として認識しなかったのかもしれません。代わりに(フォームを参照せずに)getElementByIdを使用したところ、問題なく動作しました。


挿入できるだけな.formsので、 document.forms.myform.myvar
Kai Carver

1

すでに述べたすべてに追加するために、を使用inputして、nameまたはidできればelementsオブジェクトフォームのプロパティを使用してにアクセスすることができます。そして、@ Paul D. Waiteによれば、名前と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>

HTMLFormElement.elementsページのMDNによると

HTMLFormElementプロパティ要素は、要素に含まれるすべてのフォームコントロールをリストするHTMLFormControlsCollectionを返します。独立して、lengthプロパティを使用してフォームコントロールの数だけを取得できます。

返されたコレクション内の特定のフォームコントロールにアクセスするには、インデックスまたは要素の名前またはIDを使用します。


1

nameフィールドはうまくいきます。への参照を提供しますelements

parent.children-親の名前フィールドを持つすべての要素をリストします。 parent.elements- form elementsなどのみをリストします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>

注:.elementsが機能するには、parentがである必要があり<form> tagます。一方、で.children動作しますHTML-element-など<div>, <span>, etc

幸運を...


0

フォーム2は問題なく、フォーム3も推奨されます。
名前とIDの冗長性は、互換性を維持する必要があるために発生します。html5では、いくつかの要素(img、form、iframeなど)が「name」属性を失うため、今後はそれらのIDだけを使用して参照することをお勧めしますオン :)


サーバー側の言語での使用方法が原因で、input要素がname属性を失うことはないようです。したがって、問題は残ります。name属性のみを設定している場合、標準に準拠した方法は何ですか?
セス

標準に準拠した開発では、まず、名前だけではありません。本当にIDを取得できない場合は、document.getElementByName()関数をお勧めします。
Wintermute

0

他の回答を補足するために、document.myForm.fooは、いわゆるDOMレベル0です。これは、Netscapeによって実装される方法であり、ほとんどのブラウザーでサポートされていますが、実際にはオープンスタンダードではありません。


4
名前、ID、およびインデックスによるフォームおよびフォームコントロールへのアクセスは、HTMLコレクションの DOM 2 HTML標準の一部です。
RobG、2012

0

このページをチェックしてください:https//developer.mozilla.org/En/DOM/Document.getElementsByName

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

複数の要素が同じ名前を持つ可能性があるため、これは「要素」である必要があり、配列を返す必要があります。


@robert、私はこれが良い解決策かもしれないと今思っていますが、ドキュメントの真っ直ぐなところから緊張しました:「この方法は、ドキュメントタイプとこれに対する現在の非標準の動作との間の上記の変更を考えると、使用するには疑問があるかもしれません。 XHTMLのメソッド。 "
セス、2013年

こんにちは。これに対してどのドキュメントが提案されましたか?作業しているすべてのDOM環境でxhtmlを使用している場合は、問題ないはずです。また、どのブラウザがこれをサポートしていませんか?IEのドキュメントは次のとおりです。msdn.microsoft.com / en-us / library / ms536438(VS.85).aspx上記のMozillaに加えて、他に誰がサポートしていないのでしょうか?
ロバート

0

私の答えは正確な質問では異なります。特定の要素に具体的にアクセスする場合は、document.getElementById()を使用します。例としては、複数のフィールドに基づいて構築されているため、人物のフルネームの計算がありますが、これは繰り返し可能な式です。

機能構造(フォーム)の一部として要素にアクセスする場合は、次のように使用します。

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

これは、ビジネスの観点からも機能します。ループ内の変更は、アプリケーションの機能変更に伴い、意味があります。私は主にユーザーフレンドリーな検証に適用し、間違ったデータをチェックするためのネットワーク呼び出しを防ぎます。私は検証サーバー側を繰り返します(そしてそこにさらにいくつか追加します)が、ユーザークライアント側を助けることができれば、それはすべてにとって有益です。

データの集約(フォームのデータに基づいて円グラフを作成するなど)には、構成ドキュメントとカスタムメイドのJavaScriptオブジェクトを使用します。次に、そのコンテキストに関連して重要なフィールドの正確な意味があり、私はdocument.getElementById()を使用しますか。


0

ケース[2] document.myForm.fooはInternet Exploereの方言だからです。その代わりに、私はdocument.forms.myForm.elements.fooまたはを好みdocument.forms["myForm"].elements["foo"]ます。


-1

私はこれを好む

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

2
SOへようこそ。ご意見をお寄せいただきありがとうございます。回答を編集して、理由と方法を説明してください。
B--rian
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.