フォーム、FormData オブジェクト

フォームの概要

フォーム (<form>) は、ユーザーによって送信されたデータを収集し、サーバーに送信するために使用されます。たとえば、ユーザーがサーバーに確認するためにユーザー名とパスワードを送信する場合、フォームを通過する必要があります。フォームには、開発者が使用できるさまざまなコントロールが用意されています。具体的なコントロールの種類と使用法については、HTML 言語のチュートリアルを参照してください。この章では主に JavaScript とフォーム間の対話について紹介します。

<form action="/handling-page" method="post">
  <div>
    <label for="name">ユーザー名:</label>
    <input type="text" id="name" name="ユーザー名" />
  </div>
  <div>
    <label for="passwd">パスワード:</label>
    <input type="password" id="passwd" name="user_passwd" />
  </div>
  <div>
    <input type="submit" id="submit" name="submit_button" value="submit" />
  </div>
</form>

上記のコードは、ユーザー名入力ボックス、パスワード入力ボックス、送信ボタンの 3 つのコントロールを含む単純なフォームです。

ユーザーが「送信」ボタンをクリックすると、各コントロールはキーと値のペアを生成します。キー名はコントロールの「name」属性であり、キー値はコントロールの「value」属性です。とキー値は等号で接続されます。たとえば、ユーザー名入力ボックスの name 属性は user_name で、value 属性はサーバーに送信されるときにユーザーが入力した値 (「Zhang San」と仮定) です。 user_name=Zhang Three のペアが生成されます。

すべてのキーと値のペアがサーバーに送信されます。ただし、送信されるデータ形式は、<form> 要素の method 属性に関連します。このプロパティは、データを送信するための HTTP メソッドを指定します。 GET メソッドの場合、すべてのキーと値のペアは、/handling-page?user_name=张三&user_passwd=123&submit_button=submit などの URL クエリ文字列の形式でサーバーに送信されます。 GETリクエストのHTTPヘッダ情報は以下のとおりです。

GET /handling-page?user_name=张三&user_passwd=123&submit_button=送信
ホスト: example.com

POST メソッドの場合、「user_name=张三&user_passwd=123&submit_button=submit」のように、すべてのキーと値のペアが 1 行に結合され、HTTP リクエストのデータ本体としてサーバーに送信されます。 POSTリクエストのヘッダー情報は以下のとおりです。

POST /処理ページ HTTP/1.1
ホスト: example.com
コンテンツタイプ: application/x-www-form-urlencoded
コンテンツの長さ: 74

user_name=張三&user_passwd=123&submit_button=送信

実際の送信中は、キー値が URL 内の有効な文字 (中国語の文字「Zhang San」や「submit」など) でない限り、ブラウザによって自動的にエンコードされることに注意してください。

「送信」コントロールをクリックしてフォームを送信します。

<フォーム>
  <input type="submit" value="Submit">
</form>

上記のフォームには「送信」コントロールが含まれています。このコントロールをクリックすると、ブラウザがフォーム データをサーバーに送信します。

フォーム内の <button> 要素が type 属性でタイプを指定していない場合、デフォルトで submit コントロールが使用されることに注意してください。

<フォーム>
  <button>送信</button>
</form>

上記のフォームの <button> 要素も、クリックするとフォームを送信します。

submit コントロールをクリックしてフォームを送信するだけでなく、form 要素の submit() メソッドを使用してスクリプトを通じてフォームを送信することもできます。

formElement.submit();

form 要素の reset() メソッドは、すべてのコントロールの値をリセット (デフォルト値にリセット) できます。

formElement.reset()

FormData オブジェクト

概要

フォーム データはキーと値のペアの形式でサーバーに送信され、このプロセスはブラウザーによって自動的に完了します。ただし、場合によっては、スクリプトを通じてこのプロセスを完了し、フォームのキーと値のペアを作成または編集して、スクリプトを通じてサーバーに送信したい場合があります。ブラウザーは、このジョブを実行するための FormData オブジェクトをネイティブに提供します。

FormData() は、まずフォームのインスタンスを生成するために使用されるコンストラクターです。

var formdata = 新しい FormData(form);

FormData() コンストラクターのパラメーターは DOM フォーム要素であり、コンストラクターはフォームのキーと値のペアを自動的に処理します。このパラメータはオプションです。省略すると、空のフォームが返されます。

以下はフォームです。

<form id="myForm" name="myForm">
  <div>
    <label for="username">ユーザー名:</label>
    <input type="text" id="ユーザー名" name="ユーザー名">
  </div>
  <div>
    <label for="useracc">アカウント:</label>
    <input type="text" id="useracc" name="useracc">
  </div>
  <div>
    <label for="userfile">ファイルのアップロード:</label>
    <input type="file" id="userfile" name="userfile">
  </div>
<input type="submit" value="送信!">
</form>

上記のフォームを処理するには FormData() を使用します。

var myForm = document.getElementById('myForm');
var formData = 新しい FormData(myForm);

// コントロールの値を取得します
formData.get('ユーザー名') // ""

// コントロールの値を設定します
formData.set('ユーザー名', '張三');

formData.get('ユーザー名') // "張三"

インスタンスメソッド

FormData は次のインスタンス メソッドを提供します。

  • FormData.get(key): 指定されたキー名に対応するキー値を取得します。パラメータはキー名です。同じ名前のキーと値のペアが複数ある場合は、最初のキーと値のペアのキー値が返されます。
  • FormData.getAll(key): 指定されたキー名に対応するすべてのキー値を表す配列を返します。同じ名前のキーと値のペアが複数ある場合、配列にはすべてのキー値が含まれます。
  • FormData.set(key, value): 指定されたキー名のキー値を設定します。パラメータはキー名です。キー名が存在しない場合はキーと値のペアが追加され、存在しない場合は指定されたキー名のキー値が更新されます。 2 番目のパラメータがファイルの場合は、3 番目のパラメータを使用してファイル名を表すこともできます。
  • FormData.delete(key): キーと値のペアを削除します。パラメータはキー名です。
  • FormData.append(key, value): キーと値のペアを追加します。キー名が繰り返されると、同じキー名を持つ 2 つのキーと値のペアが生成されます。 2 番目のパラメータがファイルの場合は、3 番目のパラメータを使用してファイル名を表すこともできます。
  • FormData.has(key): キー名を持つキーと値のペアが存在するかどうかを示すブール値を返します。
  • FormData.keys(): すべてのキー名をループするための for...of のトラバーサー オブジェクトを返します。
  • FormData.values(): すべてのキー値をループするための for...of のトラバーサー オブジェクトを返します。
  • FormData.entries(): すべてのキーと値のペアをループするための for...of のトラバーサー オブジェクトを返します。 for...of を直接使用して FormData インスタンスをループする場合、このメソッドがデフォルトで呼び出されます。

以下は、get()getAll()set()、および append() メソッドの例です。

var formData = 新しい FormData();

formData.set('ユーザー名', '張三');
formData.append('ユーザー名', '李思');
formData.get('ユーザー名') // "張三"
formData.getAll('username') // ["Zhang San", "李思"]

formData.append('userpic[]', myFileInput.files[0], 'user1.jpg');
formData.append('userpic[]', myFileInput.files[1], 'user2.jpg');

以下はトラバーサーの例です。

var formData = 新しい FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');

for (formData.keys() の var key) {
  コンソール.ログ(キー);
}
// "キー1"
// "キー2"

for (formData.values() の var 値) {
  console.log(値);
}
// "値1"
// "値2"

for (formData.entries() の var ペア) {
  console.log(ペア[0] + ': ' + ペア[1]);
}
// キー1: 値1
// キー2: 値2

// formData.entries() のトラバースと同等
for (formData の var ペア) {
  console.log(ペア[0] + ': ' + ペア[1]);
}
// キー1: 値1
// キー2: 値2

フォームの組み込み検証

自動検証

フォームが送信されると、ブラウザーは開発者がいくつかの条件を指定できるようにし、各フォーム コントロールの値が条件を満たしているかどうかを自動的に検証します。

<!-- 必須 -->
<入力必須>

<!-- 正規表現と一致する必要があります -->
<input pattern="バナナ|チェリー">

<!-- 文字列の長さは 6 文字である必要があります -->
<input minlength="6" maxlength="6">

<!-- 値は 1 ~ 10 でなければなりません -->
<input type="number" min="1" max="10">

<!-- 電子メール アドレスを入力する必要があります -->
<input type="電子メール">

<!-- URL を入力する必要があります -->
<入力タイプ="URL">

コントロールが検証に合格すると、「:valid」CSS 疑似クラスと一致し、ブラウザはフォーム送信プロセスを続行します。検証に失敗した場合、コントロールは :invalid CSS 疑似クラスと一致し、ブラウザはフォームの送信を終了し、エラー メッセージを表示します。

入力:無効な{
  境界線の色: 赤;
}
入力、
入力:有効 {
  境界線の色: #ccc;
}

checkValidity()

フォームの送信時にフォームを自動的に検証するだけでなく、ブラウザーは手動でフォーム検証をトリガーすることもできます。フォーム要素とフォーム コントロールの両方に、検証を手動でトリガーするための checkValidity() メソッドがあります。

// フォーム全体の検証をトリガーします
form.checkValidity()

// 単一のフォーム コントロールの検証をトリガーします
formControl.checkValidity()

「checkValidity()」メソッドはブール値を返します。「true」は検証に合格したことを意味し、「false」は検証に合格しなかったことを意味します。したがって、フォームの送信は次の関数としてカプセル化できます。

関数 submitForm(アクション) {
  var form = document.getElementById('form');
  フォーム.アクション = アクション;
  if (form.checkValidity()) {
    form.submit();
  }
}

willValidate プロパティ

コントロール要素の willValidate プロパティは、コントロールが送信時に検証されるかどうかを示すブール値です。

// HTMLコードは以下の通り
// <フォーム novalidate>
// <input id="name" name="name" 必須 />
// </form>

var input = document.querySelector('#name');
input.willValidate // true

validationMessage プロパティ

コントロール要素の validationMessage プロパティは、コントロールが検証条件を満たさない場合にブラウザによって表示されるプロンプト テキストを示す文字列を返します。次の 2 つの場合、このプロパティは空の文字列を返します。

  • このコントロールは送信時に自動的に検証されません。
  • コントロールが検証条件を満たしている
// HTMLコードは以下の通り
// <form><input type="text" 必須></form>
document.querySelector('フォーム入力').validationMessage
// 「このフィールドに入力してください。」

別の例を示します。

var myInput = document.getElementById('myinput');
if (!myInput.checkValidity()) {
  document.getElementById('prompt').innerHTML = myInput.validationMessage;
}

setCustomValidity()

コントロール要素の setCustomValidity() メソッドは、検証が失敗した場合のエラー メッセージをカスタマイズするために使用されます。カスタマイズされたエラー メッセージである文字列をパラメータとして受け入れます。パラメータが空の文字列の場合、最後に設定されたエラー メッセージがクリアされます。

このメソッドはブラウザーの組み込みフォーム検証エラー メッセージを置き換えることができ、パラメーターは表示されるエラー メッセージです。

<form action="somefile.php">
  <入力
    type="テキスト"
    名前 = "ユーザー名"
    プレースホルダー = "ユーザー名"
    パターン="[a-z]{1,15}"
    id="ユーザー名"
  >
  <input type="送信">
</form>

上記フォーム入力ボックスは小文字のみ入力可能で、15文字以内で入力可能です。入力内容が要件を満たしていない場合(例:「ABC」と入力)、フォーム送信時に Chrome ブラウザに「要求された形式と一致してください。」というエラー メッセージが表示され、フォームの送信ができなくなります。エラー メッセージを置き換えるには、以下の setCustomValidity() メソッドを使用します。

var input = document.getElementById('ユーザー名');
input.oninvalid = 関数 (イベント) {
  event.target.setCustomValidity(
    「ユーザー名は小文字である必要があり、空にすることはできず、最大 15 文字を超えることはできません」
  );
}

上記のコードでは、「invalid」イベントの listen 関数で「setCustomValidity()」メソッドが呼び出されます。このメソッドは直接呼び出すこともできます。この場合、パラメータが空の文字列でない場合、ブラウザはコントロールが検証に合格していないと判断し、このメソッドで設定されたエラー メッセージをすぐに表示します。

/* HTMLコードは以下の通り
<フォーム>
  <p><input type="file" id="fs"></p>
  <p><input type="submit"></p>
</form>
*/

document.getElementById('fs').onchange = checkFileSize;

関数 checkFileSize() {
  var fs = document.getElementById('fs');
  var ファイル = fs.files;
  if (ファイルの長さ > 0) {
     if (files[0].size > 75 * 1024) {
       fs.setCustomValidity('ファイルは 75KB を超えることはできません');
       戻る;
     }
  }
  fs.setCustomValidity('');
}

上記のコードでファイルが 75KB より大きいことが検出されると、検証が失敗するように設定され、カスタム エラー メッセージが表示されます。その後、送信ボタンをクリックすると、エラーメッセージが表示されます。このような検証失敗は自動では解消されないため、すべてのファイルが条件を満たしている場合は、エラーメッセージを空文字列に設定し、手動で検証失敗ステータスを解消してください。

有効性属性

コントロール要素の validity プロパティは、現在の検証ステータスに関する情報を含む ValidityState オブジェクトを返します。

このオブジェクトには次のプロパティがあり、すべて読み取り専用です。

  • ValidityState.badInput: ユーザーが値ボックスに文字列を入力するなど、ブラウザーがユーザーの入力を正しいタイプに変換できないかどうかを示すブール値。
  • ValidityState.customError: 検証情報を空でない文字列に設定するために setCustomValidity() メソッドが呼び出されたかどうかを示すブール値。
  • ValidityState.patternMismatch: ユーザーが入力した値がパターンの要件を満たしていないかどうかを示すブール値。
  • ValidityState.rangeOverflow: ユーザーが入力した値が最大範囲を超えているかどうかを示すブール値。
  • ValidityState.rangeUnderflow: ユーザーが入力した値が最小範囲より小さいかどうかを示すブール値。
  • ValidityState.stepMismatch: ユーザーが入力した値がステップ設定に準拠していないことを示すブール値 (つまり、ステップ値で均等に分割できない)。
  • ValidityState.tooLong: ユーザーが入力した単語数が最大単語数を超えていることを示すブール値。
  • ValidityState.tooShort: ユーザーが入力した文字が最小単語数未満であることを示すブール値。
  • ValidityState.typeMismatch: ブール値。ユーザーが入力した値がタイプの要件を満たしていないことを示します (主にタイプが電子メールまたは URL の場合)。
  • ValidityState.valid: ユーザーがすべての検証条件を満たしているかどうかを示すブール値。
  • ValidityState.valueMissing: ユーザーが必要な値を入力しなかったことを示すブール値。

以下に例を示します。

var input = document.getElementById('myinput');
if (input.validity.valid) {
  console.log('検証に合格しました');
} それ以外 {
  console.log('検証に失敗しました');
}

別の例を示します。

var txt = '';
if (document.getElementById('myInput').validity.rangeOverflow) {
  txt = '値が上限を超えています';
}
document.getElementById('prompt').innerHTML = txt;

ブラウザーがフォーム検証エラー メッセージをポップアップ表示しないようにしたい場合は、「invalid」イベントをリッスンできます。

var input = document.getElementById('ユーザー名');
var form = document.getElementById('form');

var elem = document.createElement('div');
elem.id = '通知';
elem.style.display = 'なし';
form.appendChild(elem);

input.addEventListener('無効', 関数 (イベント) {
  イベント.preventDefault();
  if (!event.target.validity.valid) {
    elem.textContent = 'ユーザー名は小文字である必要があります';
    elem.className = 'エラー';
    elem.style.display = 'ブロック';
    input.className = '無効なアニメーション シェイク';
  }
});

input.addEventListener('input', function(event){
  if ( 'block' === elem.style.display ) {
    input.className = '';
    elem.style.display = 'なし';
  }
});

上記のコードでは、「無効」イベントが発生すると (フォーム検証が失敗すると)、「event.preventDefault()」を使用してブラウザーがデフォルトの検証失敗プロンプトをポップアップ表示しないようにし、カスタマイズされたエラー プロンプト ボックスを設定します。

フォームの novalidate 属性

form 要素の HTML 属性 novalidate を使用すると、ブラウザの自動検証をオフにすることができます。

<フォームの検証>
</form>

このプロパティはスクリプトでも設定できます。

form.noValidate = true;

form 要素に novalidate 属性が設定されていない場合、送信ボタン (<button> または <input> 要素) の formnovalidate 属性は同じ効果を持ちます。

<フォーム>
  <input type="submit" value="submit" formnovalidate>
</form>

enctype 属性

フォームは 4 つのエンコーディングを使用してデータをサーバーに送信できます。エンコード形式は、フォームの enctype 属性によって決まります。

フォームに「foo」と「baz」という 2 つのフィールドがあるとします。「foo」フィールドの値は「bar」に等しく、「baz」フィールドの値は 2 行に分割された文字列です。

最初の行。
2行目。

次の 4 つの形式はすべて、このフォームをサーバーに送信できます。

(1)GETメソッド

フォームが「GET」メソッドを使用してデータを送信する場合、「enctype」属性は効果がありません。

<フォーム
  アクション = "登録.php"
  メソッド = "取得"
  onsubmit="AJAXSubmit(this); return false;"
>
</form>

データは URL のクエリ文字列として出力されます。

?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.

(2)application/x-www-form-urlencoded

フォームが POST メソッドを使用してデータを送信し、enctype 属性が省略されている場合、データは application/x-www-form-urlencoded 形式で送信されます (これがデフォルトです)。

<フォーム
  アクション = "登録.php"
  メソッド = "投稿"
  onsubmit="AJAXSubmit(this); return false;"
>
</form>

送信されるHTTPリクエストは以下の通りです。

コンテンツタイプ: application/x-www-form-urlencoded

foo=bar&baz=The+first+line.%0D%0AThe+2+line.%0D%0A

上記のコードでは、データ本体の %0D%0A が改行文字 (\r\n) を表します。

(3)テキスト/プレーン

フォームがデータの送信に POST メソッドを使用し、enctype 属性が text/plain である場合、データはプレーン テキスト形式で送信されます。

<フォーム
  アクション = "登録.php"
  メソッド = "投稿"
  enctype="テキスト/プレーン"
  onsubmit="AJAXSubmit(this); return false;"
>
</form>

送信されるHTTPリクエストは以下の通りです。

コンテンツタイプ: テキスト/プレーン

foo=バー
baz=最初の行。
2行目。

(4)マルチパート/フォームデータ

フォームが POST メソッドを使用し、enctype 属性が multipart/form-data である場合、データは混合形式で送信されます。

<フォーム
  アクション = "登録.php"
  メソッド = "投稿"
  enctype="マルチパート/フォームデータ"
  onsubmit="AJAXSubmit(this); return false;"
>
</form>

送信されるHTTPリクエストは以下の通りです。

コンテンツ タイプ: multipart/form-data; 境界=---------------314911788813839

------------------------314911788813839
コンテンツの配置: フォームデータ名 = "foo"

バー
------------------------314911788813839
コンテンツの配置: フォームデータ名 = "baz"

最初の行。
2行目。

------------------------314911788813839--

この形式は、ファイルのアップロードの形式でもあります。

ファイルのアップロード

ユーザーはフォームからもファイルをアップロードします。具体的には、ファイル入力ボックスでローカル ファイルを選択し、フォームを送信すると、ブラウザによってファイルがサーバーに送信されます。

<input type="file" id="file" name="myFile">

さらに、フォーム <form> 要素の method 属性を POST に設定し、enctype 属性を multipart/form-data に設定する必要もあります。このうち、「enctype」属性は、HTTP ヘッダー情報の「Content-Type」フィールドの値を決定します。デフォルトでは、このフィールドの値は「application/x-www-form-urlencoded」である必要があります。ファイルアップロード時は「multipart/form-data」に変更されました。

<form method="post" enctype="multipart/form-data">
  <div>
    <label for="file">ファイルを選択</label>
    <input type="file" id="file" name="myFile" multiple>
  </div>
  <div>
    <input type="submit" id="submit" name="submit_button" value="アップロード" />
  </div>
</form>

上記の HTML コードでは、ファイル コントロールの「multiple」属性は、一度に複数のファイルを選択できることを指定しています。この属性がないと、一度に 1 つのファイルしか選択できません。

var fileSelect = document.getElementById('file');
var files = fileSelect.files;

次に、サーバーに送信されるフォーム データをシミュレートする新しい FormData インスタンス オブジェクトを作成し、選択したファイルをこのオブジェクトに追加します。

var formData = 新しい FormData();

for (var i = 0; i < files.length; i++) {
  var ファイル = ファイル[i];

  //画像ファイルのみをアップロードします
  if (!file.type.match('image.*')) {
    続く;
  }

  formData.append('写真[]', file, file.name);
}

最後に、Ajax を使用してファイルをサーバーにアップロードします。

var xhr = 新しい XMLHttpRequest();

xhr.open('POST', 'handler.php', true);

xhr.onload = 関数 () {
  if (xhr.status !== 200) {
    console.log('エラーが発生しました!');
  }
};

xhr.send(フォームデータ);

FormData インスタンスの送信に加えて、AJAX 経由でファイルを直接送信することもできます。

var file = document.getElementById('test-input').files[0];
var xhr = 新しい XMLHttpRequest();

xhr.open('POST', 'myserver/uploads');
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(ファイル);

参考リンク


作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0