12

2つの送信ボタンがある単純なフォームを考えてみましょう

<form method="post">
 <button type="submit" name="command" value="cancel">Cancel Order</button>
 <button type="submit" name="command" value="proceed">Save Order</button>
</form>

送信されると、サーバーはの値をチェックすることにより、フォームの送信に使用された送信ボタンを認識しますcommand。素晴らしい!

この場合、フォームのonsubmitイベントハンドラーを使用して、AJAXを介してフォームデータを前処理して送信しています。このような:<form method="post" onsubmit="return ajaxSubmit(this);">

私はこのajaxSubmit関数を、提供されたフォームの要素をチェックし、代わりにAjaxを介してデータを送信する一般的な方法として使用しています。これは、チェックボックスが「チェックされている」場合、グループ内でどのラジオが選択されているかなど、テキストフィールドの値を決定するために正常に機能します。送信ボタンを使用してフォームを送信しました。つまりmyForm["command"]、2つのコマンドボタンのどちらが実際に使用されたかを知ることはできません。

代わりに、サーバーが送信する前にJavaScriptで受信するのと同じ「投稿」データにアクセスする方法はありますか?

そうでなければ、これは私が回避する必要がある単なる欠陥ですか?最善の方法は何ですか?

編集: すべての最新のブラウザは、フォームの送信に使用されるボタンの名前/値を渡すので(グループから選択されたオプション、チェックボックスの名前/値などの他の関連部分とともに)、誰でもその理由を説明できますサーバーに送信される前にこのデータに直接アクセスする方法はありませんか?できないはずの理由はありますか?

4

4 に答える 4

17

代わりに、サーバーが送信する前にJavaScriptで受信するのと同じ「投稿」データにアクセスする方法はありますか?

正確なデータではありません。

submitどのボタンが押されたかを知る通常の方法は、(残念ながら)clickハンドラーをボタンにアタッチし、変数(またはフィールドの値)を設定してもらうことです。これにより、イベントハンドラーhiddenをチェックインできます。submit

古いスタイルのDOM0イベントハンドラー属性を使用しているため、おそらくhiddenフィールドは実行している内容によりよく適合します。

<form method="post">
 <input type="hidden" name="submitclicked" value="">
 <button type="submit" name="command" value="cancel" onclick="submitClick(this);">Cancel Order</button>
 <button type="submit" name="command" value="proceed" onclick="submitClick(this);">Save Order</button>
</form>

...submitClickこのように見える場所:

function submitClick(button) {
    button.form.submitclicked.value = button.value;
}

...ただし、代わりにDOM2スタイルのイベントハンドラーを使用するか、少なくともDOM0ハンドラーをコードブロックにアタッチすることをお勧めします。グローバル関数の作成を回避したり、グローバル変数を作成せずにデータを共有したりできるためです。


明確にするonclickために、すべての要素に属性を指定する必要はありません。上記で指定した唯一の理由は、DOM0ハンドラーを使用していたためです。

それを処理するためのより良い方法は、イベントバブリングを使用することです。イベントはclick、送信ボタンを含む子孫コントロールからフォームにバブルアップするため、フォームにイベントをフックして、送信ボタンで発生したかどうか、発生した場合はそのボタンが何であるかを確認できますvalue

たとえば、ここでは、フォームに動的にアタッチされたDOM0ハンドラーを使用して、クリックされた送信ボタンの値を警告します。

var form = document.getElementById("theForm");
form.onclick = function(e) {
  // Get the event
  e = e || window.event;

  // Did it originate in an input[type=submit]?
  if (e.target.tagName === "INPUT" &&
      e.target.type === "submit") {
    // Yes
    alert(e.target.value);
  }
};

実例| ソース

または、最新のブラウザーでDOM2ハンドラーを使用します(IE8以前ではattachEventありませんが、それらを追加するのは簡単です。これは、 addEventListener[そしてそれよりも前の]ほぼ同じことを行います)。

document.getElementById("theForm").addEventListener("click", function(e) {
  // Did it originate in an input[type=submit]?
  if (e.target.tagName === "INPUT" &&
      e.target.type === "submit") {
    // Yes
    alert(e.target.value);
  }
}, false);

実例| ソース

または、ライブラリを使用して簡単にします(ここでは、jQueryですが、ほとんどの場合、イベント委任と呼ばれるこの機能があります)。

$("#theForm").delegate("input[type=submit]", "click", function() {
  alert(this.value);
  return false;
});

実例| ソースdelegate明快さが好きなのでここで使用しています。最近のバージョンのjQueryでは、ハイパーオーバーロードを使用できonますが、あまり明確ではありません。選択する場合は、引数の順序が異なることに注意してください。)

ここでのポイントは、それが複雑でも、困難でも、特に面倒でもないということです。

編集の最後の質問を再確認してください。

...サーバーに送信される前にこのデータに直接アクセスする方法がない理由を誰かが説明できますか?

おそらくそうではありません。このようなものの多くは進化したばかりであることを理解することが重要です。フォームとともに送信される送信ボタンの値はHTMLのものです。どうやら、DOM HTMLフォームモジュールを実行しているとき、「ねえ、フォーム内にのみ存在するプロパティがフォームにあるはずです」と言うことは誰にも起こりませんでした。フォームを送信した内容を通知する送信イベント。」おそらく誰かに起こったはずですが、明らかにそうではありませんでした。

于 2012-12-19T11:04:18.600 に答える
4

別の解決策は、送信ボタンの代わりにラジオボタンを使用することです(ただし、ボタンのように見えるようにラジオを設計する必要があります)。

送信後、フィールドの値はクリックされた値になります。$("[name=command]:selected]")jQueryの、またはを使用して、選択したオプションをフェッチできます。$("#theForm").serialize()

<form method="post" onsubmit="return ajaxSubmit(this);" id="theForm">
 <input type="radio" name="command" value="cancel" id="cancel" onClick="document.getElementById('theForm').submit();">
 <label for="cancel">Cancel Order</label>

 <input type="radio" name="command" value="proceed" id="proceed" onClick="document.getElementById('theForm').submit();">
 <label for="proceed">Save Order</label>
</form>
于 2012-12-29T02:52:16.890 に答える
2

クリックされなかったもう一方のボタンを削除することで、これを回避できると思います。その後、jQueryのserialize()を実行するか、他の方法で残されたボタンの値にアクセスできます。

コードは次のようになります。

<form method="post">
 <button type="submit" id=cancel name="command" value="cancel" onclick="document.getElementByid('submit').remove();submitClick(this);">Cancel Order</button>
 <button type="submit" id=submit name="command" value="proceed" onclick="document.getElementByid('cancel').remove();submitClick(this);">Save Order</button>
</form>
于 2012-12-29T02:37:23.210 に答える
1

すべて合理的ですが、すべての送信ボタンにクリックハンドラーをアタッチする場合は、送信機能のフープを調べて送信の詳細を管理することはあまり意味がありません。

クリックハンドラーがフォームの送信をトリガーし、十分なコンテキスト情報をミックスに渡すようにするだけです。待ってください。クリックハンドラーは通常、クリックのソースを既に通知します(コンテキスト情報があります)。特に、jQuery風のフレームワークを使用している場合はそうです。

したがって、代わりに:

<form onsubmit="doSubmit()" ...>
<input type="submit" onclick="updateSourceTo('cancel');" ... />
<input type="submit" onclick="updateSourceTo('submit');" ... />

使用する:

<form ...>
<input type="button" onclick="doSubmit('cancel');" ... />
<input type="button" onclick="doSubmit('submit');" ... />

または、クリックイベントターゲットを確認してソースを検出する場合は、次のようにします。

<form ...>
<input type="button" onclick="handleSubmitButtonClick();" ... />
<input type="button" onclick="handleSubmitButtonClick();" ... />

handleSubmitButtonClickの本質的な詳細については、form.submit()やjQueryのevent.targetなどについて言及する必要があります。

私は、submit-onsubmitパラダイムを維持することで、フォーム処理に特定の純粋性が促進されることを認めますが、IMOは、2つの送信ボタンを使用して非純粋な土地にすでに足を踏み入れています。

于 2013-01-02T05:17:23.753 に答える