Form, FormData object

Form overview

The form (<form>) is used to collect the data submitted by the user and send it to the server. For example, if a user submits a user name and password to be authenticated by the server, they must pass a form. The form provides a variety of controls for developers to use. For specific control types and usage, please refer to the HTML language tutorial. This chapter mainly introduces the interaction between JavaScript and forms.

<form action="/handling-page" method="post">
  <div>
    <label for="name">Username:</label>
    <input type="text" id="name" name="user_name" />
  </div>
  <div>
    <label for="passwd">Password:</label>
    <input type="password" id="passwd" name="user_passwd" />
  </div>
  <div>
    <input type="submit" id="submit" name="submit_button" value="Submit" />
  </div>
</form>

The above code is a simple form with three controls: a username input box, a password input box and a submit button.

When the user clicks the "Submit" button, each control will generate a key-value pair. The key name is the control's name property, and the key value is the control's value property. The key name and the key value are connected by an equal sign. For example, the name attribute of the username input box is user_name, and the value attribute is the value entered by the user. If it is "Zhang San", when submitted to the server, a key-value pair user_name=Zhang is generated. Three.

All key-value pairs will be submitted to the server. However, the format of the submitted data is related to the method attribute of the <form> element. This attribute specifies the HTTP method for submitting data. If it is the GET method, all key-value pairs will be submitted to the server in the form of URL query strings, such as /handling-page?user_name=Zhang San&user_passwd=123&submit_button=submit. The following is the HTTP header information of the GET request.

GET /handling-page?user_name=Zhang San&user_passwd=123&submit_button=Submit
Host: example.com

If it is the POST method, all key-value pairs will be concatenated into one line and sent to the server as the data body of the HTTP request, such as user_name=Zhang San&user_passwd=123&submit_button=submit. The following is the header information of the POST request.

POST /handling-page HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 74

user_name=Zhang San&user_passwd=123&submit_button=Submit

Note that when actually submitting, as long as the key value is not a legal character of the URL (such as the Chinese characters "Zhang San" and "Submit"), the browser will automatically encode it.

Click the submit control to submit the form.

<form>
  <input type="submit" value="Submit" />
</form>

The above form contains a submit control, click this control, the browser will submit the form data to the server.

Note that if the <button> element in the form does not specify the type with the type attribute, then the default is the submit control.

<form>
  <button>Submit</button>
</form>

The <button> element of the above form will also submit the form when clicked.

In addition to clicking the submit control to submit the form, you can also use the submit() method of the form element to submit the form through a script.

formElement.submit();

The reset() method of form elements can reset the values ​​of all controls (reset to default values).

formElement.reset();

FormData Object

Overview

The form data is sent to the server in the form of key-value pairs, and this process is automatically completed by the browser. But sometimes, we want to complete this process through a script, construct or edit the key-value pairs of the form, and then send it to the server through the script. The browser natively provides the FormData object to accomplish this task.

FormData() is first a constructor function to generate an instance of the form.

var formdata = new FormData(form);

The parameter of the FormData() constructor is a DOM form element, and the constructor will automatically process the key-value pairs of the form. This parameter is optional. If it is omitted, it means an empty form.

Below is a form.

<form id="myForm" name="myForm">
  <div>
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" />
  </div>
  <div>
    <label for="useracc">Account:</label>
    <input type="text" id="useracc" name="useracc" />
  </div>
  <div>
    <label for="userfile">Upload files:</label>
    <input type="file" id="userfile" name="userfile" />
  </div>
  <input type="submit" value="Submit!" />
</form>

We use FormData() to process the above form.

var myForm = document.getElementById("myForm");
var formData = new FormData(myForm);

// Get the value of a control
formData.get("username"); // ""

// Set the value of a control
formData.set("username", "Zhang San");

formData.get("username"); // "Zhang San"

Example method

FormData provides the following example methods.

-FormData.get(key): Get the key value corresponding to the specified key name, the parameter is the key name. If there are multiple key-value pairs with the same name, the key-value of the first key-value pair is returned. -FormData.getAll(key): returns an array representing all the key values ​​corresponding to the specified key name. If there are multiple key-value pairs with the same name, the array will contain all the key-values. -FormData.set(key, value): Set the key value of the specified key name, the parameter is the key name. If the key name does not exist, the key-value pair will be added, otherwise the key-value of the specified key name will be updated. If the second parameter is a file, you can also use the third parameter to indicate the file name. -FormData.delete(key): delete a key-value pair, the parameter is the key name. -FormData.append(key, value): add a key-value pair. If the key name is repeated, two key-value pairs with the same key name will be generated. If the second parameter is a file, you can also use the third parameter to indicate the file name. -FormData.has(key): returns a boolean value indicating whether there is a key-value pair with the key name. -FormData.keys(): returns a iterator object, used for for...of to loop through all the key names. -FormData.values(): returns a iterator object, used in for...of loop to traverse all key values. -FormData.entries(): returns an iterator object, used for for...of to loop through all key-value pairs. If you directly loop through the FormData instance with for...of, this method will be called by default.

The following are examples of get(), getAll(), set(), and append() methods.

var formData = new FormData();

formData.set("username", "Zhang San");
formData.append("username", "李四");
formData.get("username"); // "Zhang San"
formData.getAll("username"); // ["Zhang San", "李四"]

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

The following is an example of a iterator.

var formData = new FormData();
formData.append("key1", "value1");
formData.append("key2", "value2");

for (var key of formData.keys()) {
  console.log(key);
}
// "key1"
// "key2"

for (var value of formData.values()) {
  console.log(value);
}
// "value1"
// "value2"

for (var pair of formData.entries()) {
  console.log(pair[0] + ": " + pair[1]);
}
// key1: value1
// key2: value2

// equivalent to traversing formData.entries()
for (var pair of formData) {
  console.log(pair[0] + ": " + pair[1]);
}
// key1: value1
// key2: value2

Built-in validation of forms

Automatic verification

When the form is submitted, the browser allows the developer to specify some conditions, and it will automatically verify whether the value of each form control meets the conditions.

<!-- Required-->
<input required />

<!-- Must conform to regular expression -->
<input pattern="banana|cherry" />

<!-- The length of the string must be 6 characters -->
<input minlength="6" maxlength="6" />

<!-- The value must be between 1 and 10 -->
<input type="number" min="1" max="10" />

<!-- Email address must be filled in -->
<input type="email" />

<!-- URL must be filled in -->
<input type="URL" />

If a control passes validation, it will match the CSS pseudo-class of :valid, and the browser will continue the form submission process. If it fails the validation, the control will match the CSS pseudo-class of :invalid, the browser will terminate the form submission and display an error message.

input:invalid {
  border-color: red;
}
input,
input:valid {
  border-color: #ccc;
}

checkValidity()

In addition to automatically verifying the form when the form is submitted, the browser can also manually trigger the verification of the form. Both form elements and form controls have a checkValidity() method, which is used to manually trigger verification.

// Trigger the verification of the entire form
form.checkValidity();

// Trigger verification of a single form control
formControl.checkValidity();

The checkValidity() method returns a boolean value, true means passing the verification, and false means not passing the verification. Therefore, the submission form can be encapsulated as the following function.

function submitForm(action) {
  var form = document.getElementById("form");
  form.action = action;
  if (form.checkValidity()) {
    form.submit();
  }
}

willValidate attribute

The willValidate property of the control element is a boolean value indicating whether the control will be validated when submitted.

// HTML code is as follows
// <form novalidate>
// <input id="name" name="name" required />
// </form>

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

validationMessage property

The validationMessage property of the control element returns a string indicating the prompt text displayed by the browser when the control does not meet the verification conditions. In the following two cases, this attribute returns an empty string.

-The control will not be automatically verified when submitted -The control meets the verification conditions

// HTML code is as follows
// <form><input type="text" required></form>
document.querySelector("form input").validationMessage;
// "Please fill in this field."

Here is another example.

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

setCustomValidity()

The setCustomValidity() method of the control element is used to customize the error message when the validation fails. It accepts a string as a parameter, which is a customized error message. If the parameter is an empty string, the error message set last time is cleared.

This method can replace the browser's built-in form validation error message, and the parameter is the error message to be displayed.

<form action="somefile.php">
  <input
    type="text"
    name="username"
    placeholder="Username"
    pattern="[az]{1,15}"
    id="username"
  />
  <input type="submit" />
</form>

The above form input box requires only lowercase letters and no more than 15 characters. If the input does not meet the requirements (for example, input "ABC"), when submitting the form, the Chrome browser will pop up the error message "Please match the requested format.", prohibiting the form submission. Next, use the setCustomValidity() method to replace the error message.

var input = document.getElementById("username");
input.oninvalid = function (event) {
  event.target.setCustomValidity(
    "User name must be in lowercase letters, cannot be empty, and the longest cannot exceed 15 characters"
  );
};

In the above code, the setCustomValidity() method is called in the listener function of the invalid event. This method can also be called directly. At this time, if the parameter is not an empty string, the browser will think that the control has not passed the verification and will immediately display the error message set by this method.

/* HTML code is as follows
<form>
  <p><input type="file" id="fs"></p>
  <p><input type="submit"></p>
</form>
*/

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

function checkFileSize() {
  var fs = document.getElementById("fs");
  var files = fs.files;
  if (files.length > 0) {
    if (files[0].size > 75 * 1024) {
      fs.setCustomValidity("The file cannot be larger than 75KB");
      return;
    }
  }
  fs.setCustomValidity("");
}

Once the above code finds that the file is larger than 75KB, it will set the verification to fail and give a custom error message. Then, when you click the submit button, an error message will be displayed. This kind of verification failure will not be automatically eliminated, so if all files meet the conditions, set the error message to an empty string to manually eliminate the state of verification failure.

validity property

The validity property of the control element returns a ValidityState object, which contains information about the current verification state.

The object has the following properties, all of which are read-only.

-ValidityState.badInput: Boolean value, indicating whether the browser cannot convert the user's input into the correct type, for example, the user enters a string in the numeric box. -ValidityState.customError: Boolean value, indicating whether the setCustomValidity() method has been called to set the verification information to a non-empty string. -ValidityState.patternMismatch: Boolean value, indicating whether the value entered by the user does not meet the requirements of the pattern. -ValidityState.rangeOverflow: Boolean value, indicating whether the value entered by the user is greater than the maximum range. -ValidityState.rangeUnderflow: Boolean value, indicating whether the value entered by the user is less than the minimum range. -ValidityState.stepMismatch: Boolean value, indicating that the value entered by the user does not meet the step size setting (that is, it cannot be divisible by the step size value). -ValidityState.tooLong: Boolean value, indicating that the number of words entered by the user exceeds the maximum number of words. -ValidityState.tooShort: Boolean value, indicating that the characters entered by the user are less than the shortest number of characters. -ValidityState.typeMismatch: Boolean value, indicating that the value entered by the user does not meet the type requirements (mainly when the type is Email or URL). -ValidityState.valid: Boolean value, indicating whether the user satisfies all verification conditions. -ValidityState.valueMissing: Boolean value, indicating that the user did not fill in the required value.

Below is an example.

var input = document.getElementById("myinput");
if (input.validity.valid) {
  console.log("Passed verification");
} else {
  console.log("Verification failed");
}

Here is another example.

var txt = "";
if (document.getElementById("myInput").validity.rangeOverflow) {
  txt = "The value exceeds the upper limit";
}
document.getElementById("prompt").innerHTML = txt;

If you want to prevent the browser from popping up the form validation error message, you can listen to the invalid event.

var input = document.getElementById("username");
var form = document.getElementById("form");

var elem = document.createElement("div");
elem.id = "notify";
elem.style.display = "none";
form.appendChild(elem);

input.addEventListener("invalid", function (event) {
  event.preventDefault();
  if (!event.target.validity.valid) {
    elem.textContent = "Username must be in lowercase letters";
    elem.className = "error";
    elem.style.display = "block";
    input.className = "invalid animated shake";
  }
});

input.addEventListener("input", function (event) {
  if ("block" === elem.style.display) {
    input.className = "";
    elem.style.display = "none";
  }
});

In the above code, once the invalid event (form validation failure) occurs, event.preventDefault() is used to prevent the browser from popping up the default verification failure prompt, and then set a custom error prompt box.

The novalidate attribute of the form

The HTML attribute novalidate of the form element can turn off the automatic verification of the browser.

<form novalidate></form>

This property can also be set in the script.

form.noValidate = true;

If the form element does not set the novalidate attribute, then the formnovalidate attribute of the submit button (<button> or <input> element) has the same effect.

<form>
  <input type="submit" value="submit" formnovalidate />
</form>

enctype attribute

The form can use four encodings to send data to the server. The encoding format is determined by the enctype attribute of the form.

Assume that the form has two fields, foo and baz, where the value of the foo field is equal to bar, and the value of the baz field is a string divided into two lines.

The first line.
The second line.

The following four formats can send this form to the server.

(1) GET method

If the form uses the GET method to send data, the enctype attribute is invalid.

<form
  action="register.php"
  method="get"
  onsubmit="AJAXSubmit(this); return false;"
></form>

The data will be sent out as the query string of the URL.

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

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

If the form uses the POST method to send data and the enctype attribute is omitted, then the data is sent in the format of application/x-www-form-urlencoded (because this is the default value).

<form
  action="register.php"
  method="post"
  onsubmit="AJAXSubmit(this); return false;"
></form>

The HTTP request sent is as follows.

Content-Type: application/x-www-form-urlencoded

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

In the above code, %0D%0A in the data body represents a newline character (\r\n).

(3) text/plain

If the form uses the POST method to send data and the enctype attribute is text/plain, then the data will be sent in plain text format.

<form
  action="register.php"
  method="post"
  enctype="text/plain"
  onsubmit="AJAXSubmit(this); return false;"
></form>

The HTTP request sent is as follows.

Content-Type: text/plain

foo=bar
baz=The first line.
The second line.

(4) multipart/form-data

If the form uses the POST method and the enctype attribute is multipart/form-data, then the data will be sent in a mixed format.

<form
  action="register.php"
  method="post"
  enctype="multipart/form-data"
  onsubmit="AJAXSubmit(this); return false;"
></form>

The HTTP request sent is as follows.

Content-Type: multipart/form-data; boundary=---------------------------314911788813839

-----------------------------314911788813839
Content-Disposition: form-data; name="foo"

bar
-----------------------------314911788813839
Content-Disposition: form-data; name="baz"

The first line.
The second line.

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

This format is also the format of file upload.

File Upload

Users upload files through forms. Specifically, the local file is selected through the file input box, and when the form is submitted, the browser will send the file to the server.

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

In addition, the method attribute of the form <form> element needs to be set to POST, and the enctype attribute is set to multipart/form-data. Among them, the enctype attribute determines the value of the Content-Type field of the HTTP header. By default, the value of this field is application/x-www-form-urlencoded, but it should be changed to when the file is uploaded. multipart/form-data.

<form method="post" enctype="multipart/form-data">
  <div>
    <label for="file">Select a file</label>
    <input type="file" id="file" name="myFile" multiple />
  </div>
  <div>
    <input type="submit" id="submit" name="submit_button" value="Upload" />
  </div>
</form>

In the above HTML code, the multiple attribute of the file control specifies that multiple files can be selected at a time; if there is no such attribute, only one file can be selected at a time.

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

Then, create a new instance of FormData to simulate the form data sent to the server, and add the selected file to this object.

var formData = new FormData();

for (var i = 0; i < files.length; i++) {
  var file = files[i];

  // Only upload image files
  if (!file.type.match("image.*")) {
    continue;
  }

  formData.append("photos[]", file, file.name);
}

Finally, use Ajax to upload files to the server.

var xhr = new XMLHttpRequest();

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

xhr.onload = function () {
  if (xhr.status !== 200) {
    console.log("An error occurred!");
  }
};

xhr.send(formData);

In addition to sending FormData instances, you can also send files directly via AJAX.

var file = document.getElementById("test-input").files[0];
var xhr = new XMLHttpRequest();

xhr.open("POST", "myserver/uploads");
xhr.setRequestHeader("Content-Type", file.type);
xhr.send(file);