Hầu hết các trang web và ứng dụng đều có biểu mẫu web. Các trang web đùa, chẳng hạn như DoWebsites<form>
.
Phần tử <form>
HTML xác định một điểm đánh dấu tài liệu chứa các thành phần điều khiển tương tác để gửi thông tin. Được lồng trong <form>
, bạn sẽ thấy tất cả các thành phần điều khiển biểu mẫu tương tác (và không tương tác) tạo nên biểu mẫu đó.
HTML rất mạnh mẽ. Phần này tập trung vào sức mạnh của HTML, bao gồm những gì HTML có thể làm mà không cần thêm JavaScript. Việc sử dụng dữ liệu biểu mẫu phía máy khách để cập nhật giao diện người dùng theo một cách nào đó thường liên quan đến CSS hoặc JavaScript, không được thảo luận ở đây. Có một khoá học Tìm hiểu về Biểu mẫu. Chúng tôi sẽ không lặp lại phần đó ở đây, nhưng sẽ giới thiệu một số thành phần điều khiển biểu mẫu và các thuộc tính HTML hỗ trợ các thành phần đó.
Với biểu mẫu, bạn có thể cho phép người dùng tương tác với trang web hoặc ứng dụng của bạn, xác thực thông tin đã nhập và gửi dữ liệu đến máy chủ. Thuộc tính HTML có thể cho phép yêu cầu người dùng chọn các thành phần điều khiển biểu mẫu hoặc nhập một giá trị. Thuộc tính HTML có thể xác định các tiêu chí cụ thể mà giá trị phải khớp để hợp lệ. Khi người dùng cố gắng gửi biểu mẫu, tất cả giá trị điều khiển biểu mẫu sẽ trải qua quy trình xác thực quy tắc ràng buộc phía máy khách và có thể ngăn việc gửi cho đến khi dữ liệu khớp với tiêu chí bắt buộc; tất cả đều không cần JavaScript. Bạn cũng có thể tắt tính năng này: đặt thuộc tính novalidate
trên <form>
hoặc thường là formnovalidate
trên một nút, lưu dữ liệu biểu mẫu để hoàn tất sau này, ngăn việc xác thực.
Gửi biểu mẫu
Biểu mẫu được gửi khi người dùng kích hoạt nút gửi lồng trong biểu mẫu. Khi sử dụng <input>
cho các nút, "value" là nhãn của nút và hiển thị trong nút đó. Khi sử dụng <button>
, nhãn là văn bản nằm giữa thẻ mở và thẻ đóng <button>
. Bạn có thể viết nút gửi theo một trong hai cách sau:
<input type="submit" value="Submit Form">
<button type="submit">Submit Form</button>
Đối với một biểu mẫu rất đơn giản, bạn cần có một phần tử <form>
, với một số mục nhập biểu mẫu bên trong và một nút gửi. Tuy nhiên, bạn không chỉ cần gửi biểu mẫu mà còn có thể gửi biểu mẫu.
Các thuộc tính của phần tử <form>
đặt phương thức HTTP mà qua đó biểu mẫu được gửi và URL xử lý việc gửi biểu mẫu. Có, bạn có thể gửi, xử lý biểu mẫu và tải trang mới mà không cần JavaScript. Phần tử <form>
rất mạnh mẽ.
Giá trị thuộc tính action
và method
của phần tử <form>
lần lượt xác định URL xử lý dữ liệu biểu mẫu và phương thức HTTP dùng để gửi dữ liệu.
Theo mặc định, dữ liệu biểu mẫu được gửi đến trang hiện tại. Nếu không, hãy đặt thuộc tính action
thành URL của nơi dữ liệu sẽ được gửi đến.
Dữ liệu được gửi bao gồm các cặp tên/giá trị của nhiều thành phần điều khiển biểu mẫu. Theo mặc định, thuộc tính này bao gồm tất cả các thành phần điều khiển biểu mẫu được lồng trong biểu mẫu có name
. Tuy nhiên, với thuộc tính form
, bạn có thể đưa các thành phần điều khiển biểu mẫu vào bên ngoài <form>
và bỏ qua các thành phần điều khiển biểu mẫu lồng trong <form>
. Được hỗ trợ trên các thành phần điều khiển biểu mẫu và <fieldset>
, thuộc tính form
lấy giá trị là id
của biểu mẫu mà thành phần điều khiển được liên kết, không nhất thiết phải là biểu mẫu mà thành phần điều khiển được lồng trong đó. Điều này có nghĩa là các thành phần điều khiển biểu mẫu không cần được lồng trong <form>
.
Thuộc tính method
xác định giao thức HTTP của yêu cầu: thường là GET
hoặc POST
. Với GET
, dữ liệu biểu mẫu được gửi dưới dạng chuỗi thông số của các cặp name=value
, nối thêm vào URL của action
.
Với POST
, dữ liệu được thêm vào phần nội dung của yêu cầu HTTP. Khi gửi dữ liệu bảo mật, chẳng hạn như mật khẩu và thông tin thẻ tín dụng, hãy luôn sử dụng POST
.
Ngoài ra, còn có phương thức DIALOG
. Nếu <form method="dialog">
nằm trong <dialog>
, thì việc gửi biểu mẫu sẽ đóng hộp thoại; có một sự kiện gửi mặc dù dữ liệu không được xoá hoặc gửi. Xin nhắc lại, không cần JavaScript. Vấn đề này sẽ được thảo luận trong phần hộp thoại. Xin lưu ý rằng vì thao tác này không gửi biểu mẫu, nên bạn có thể muốn đưa cả formmethod="dialog"
và formnovalidate
vào nút gửi.
Nút biểu mẫu có thể có nhiều thuộc tính hơn những thuộc tính được mô tả ở đầu phần này. Nếu nút đó có thuộc tính formaction
, formenctype
, formmethod
, formnovalidate
hoặc formtarget
, thì các giá trị được đặt trên nút để kích hoạt việc gửi biểu mẫu sẽ được ưu tiên hơn action
, enctype
, method
và target
được đặt cho <form>
. Quá trình xác thực quy tắc ràng buộc diễn ra trước khi gửi biểu mẫu, nhưng chỉ khi không có formnovalidate
trên nút gửi đã kích hoạt hoặc novalidate
trên <form>
.
Để ghi lại nút nào đã được dùng để gửi biểu mẫu, hãy cung cấp cho nút đó một name
. Các nút không có tên hoặc giá trị sẽ không được gửi cùng với dữ liệu biểu mẫu khi gửi biểu mẫu.
Sau khi gửi biểu mẫu
Khi người dùng gửi một biểu mẫu trực tuyến đã hoàn tất, tên và giá trị của các thành phần điều khiển biểu mẫu có liên quan sẽ được gửi. Tên là giá trị của thuộc tính name
. Các giá trị này đến từ nội dung của thuộc tính value
hoặc giá trị do người dùng nhập hoặc chọn. Giá trị của <textarea>
là văn bản bên trong.
Giá trị của <select>
là value
của <option>
đã chọn hoặc nếu <option>
không bao gồm thuộc tính value
, thì giá trị này là văn bản bên trong của tuỳ chọn đã chọn.
<form method="GET">
<label for="student">Pick a student:</label>
<select name="student" id="student">
<option value="hoover">Hoover Sukhdeep</option>
<option>Blendan Smooth</option>
<option value="toasty">Toasty McToastface</option>
</select>
<input type="submit" value="Submit Form">
</form>
Việc chọn "Hoover Sukhdeep" (hoặc không làm gì cả, vì trình duyệt sẽ hiển thị và do đó chọn giá trị tuỳ chọn đầu tiên theo mặc định) rồi nhấp vào nút gửi sẽ tải lại trang này, đặt URL thành:
https://web.dev/learn/html/forms?student=hoover
Vì tuỳ chọn thứ hai không có thuộc tính value
, nên văn bản bên trong sẽ được gửi dưới dạng giá trị. Việc chọn "Blendan Smooth" và nhấp vào nút gửi sẽ tải lại trang này, đặt URL thành:
https://web.dev/learn/html/forms?student=Blendan+Smooth
Khi một biểu mẫu được gửi, thông tin được gửi bao gồm tên và giá trị của tất cả các thành phần điều khiển biểu mẫu được đặt tên có name
ngoại trừ các hộp đánh dấu không được chọn, nút chọn không được chọn, tên và giá trị của bất kỳ nút nào khác ngoài nút gửi biểu mẫu. Đối với tất cả các thành phần điều khiển biểu mẫu khác, nếu thành phần điều khiển biểu mẫu có tên nhưng không có giá trị nào được nhập hoặc giá trị mặc định, thì name
của thành phần điều khiển biểu mẫu sẽ được gửi với giá trị trống.
Có 22 loại dữ liệu đầu vào, vì vậy, chúng tôi không thể đề cập đến tất cả các loại dữ liệu đầu vào.
Xin lưu ý rằng việc thêm một giá trị là không bắt buộc và thường không nên làm khi bạn muốn người dùng nhập thông tin.
Đối với các phần tử <input>
mà người dùng không thể chỉnh sửa giá trị, bạn phải luôn thêm một giá trị, kể cả các phần tử đầu vào có loại hidden
, radio
, checkbox
, submit
, button
và reset
.
Bạn nên sử dụng name
riêng biệt cho các thành phần điều khiển biểu mẫu để đơn giản hoá quá trình xử lý dữ liệu phía máy chủ. Hộp đánh dấu và nút chọn là các trường hợp ngoại lệ đối với quy tắc này.
Nút chọn
Nếu bạn từng nhận thấy rằng khi chọn một nút chọn trong một nhóm nút chọn, bạn chỉ có thể chọn một nút chọn tại một thời điểm, thì đó là do thuộc tính name
. Hiệu ứng chỉ-có-thể-chọn-một-nút này được tạo bằng cách gán cho mỗi nút chọn trong một nhóm cùng một name
.
name
phải là duy nhất cho nhóm: nếu bạn vô tình sử dụng cùng một name
cho hai nhóm riêng biệt, thì việc chọn một nút chọn trong nhóm thứ hai sẽ bỏ chọn mọi lựa chọn đã thực hiện trong nhóm đầu tiên bằng cùng một name
.
name
cùng với value
của nút chọn sẽ được gửi cùng với biểu mẫu. Đảm bảo mỗi nút chọn đều có một value
phù hợp (và thường là duy nhất). Các giá trị của nút chọn không được chọn sẽ không được gửi.
Bạn có thể có bao nhiêu nhóm nút chọn trên một trang tuỳ thích, với mỗi nhóm hoạt động độc lập, miễn là mỗi nhóm đều có một name
riêng biệt.
Nếu bạn muốn tải trang bằng một trong các nút chọn trong một nhóm có cùng tên được chọn, hãy thêm thuộc tính checked
.
Nút chọn này sẽ khớp với lớp giả CSS :default
, ngay cả khi người dùng chọn một nút chọn khác. Nút chọn hiện đang được chọn khớp với lớp giả :checked
.
Nếu người dùng bắt buộc phải chọn một thành phần điều khiển nút chọn trong một nhóm nút chọn, hãy thêm thuộc tính required
vào ít nhất một thành phần điều khiển. Việc đưa required
vào nút chọn trong một nhóm sẽ thực hiện một lựa chọn bắt buộc để gửi biểu mẫu nhưng không nhất thiết phải là đài có thuộc tính được chọn là hợp lệ. Ngoài ra, hãy nêu rõ trong <legend>
rằng cần phải có quyền kiểm soát biểu mẫu. Việc gắn nhãn cho các nhóm nút chọn cùng với từng nút riêng lẻ sẽ được mô tả sau.
Hộp kiểm
Tất cả các hộp đánh dấu trong một nhóm đều có cùng một name
. Chỉ những hộp đánh dấu đã chọn mới có name
và value
được gửi cùng với biểu mẫu. Nếu bạn chọn nhiều hộp đánh dấu có cùng tên, thì cùng một tên sẽ được gửi với (hy vọng là) các giá trị khác nhau. Nếu bạn có nhiều thành phần điều khiển biểu mẫu có cùng tên, ngay cả khi không phải tất cả đều là hộp đánh dấu, thì tất cả các thành phần đó sẽ được gửi, được phân tách bằng ký tự &.
Nếu bạn không thêm value
vào hộp đánh dấu, giá trị của các hộp đánh dấu đã chọn sẽ mặc định là on
, điều này có thể không giúp ích gì. Nếu bạn có ba hộp đánh dấu tên là chk
và tất cả đều được đánh dấu, thì hệ thống sẽ không giải mã được nội dung gửi biểu mẫu:
https://web.dev/learn/html/forms?chk=on&chk=on&chk=on
Để tạo hộp đánh dấu bắt buộc, hãy thêm thuộc tính required
. Luôn thông báo cho người dùng khi họ phải đánh dấu vào hộp đánh dấu hoặc khi cần bất kỳ thành phần điều khiển biểu mẫu nào. Việc thêm required
vào một hộp đánh dấu chỉ khiến hộp đánh dấu đó trở thành hộp đánh dấu bắt buộc; thao tác này không ảnh hưởng đến các hộp đánh dấu khác có cùng tên.
Nhãn và fieldset
Để người dùng biết cách điền vào biểu mẫu, biểu mẫu đó phải truy cập được. Mỗi thành phần điều khiển biểu mẫu phải có nhãn.
Bạn cũng nên gắn nhãn cho các nhóm thành phần điều khiển biểu mẫu. Mặc dù các vùng nhập, chọn và văn bản riêng lẻ được gắn nhãn bằng <label>
, nhưng các nhóm thành phần điều khiển biểu mẫu được gắn nhãn theo nội dung của <legend>
của <fieldset>
nhóm các thành phần đó lại với nhau.
Trong các ví dụ trước, bạn có thể nhận thấy rằng mỗi thành phần điều khiển biểu mẫu (ngoại trừ nút gửi) đều có <label>
. Nhãn cung cấp các thành phần điều khiển biểu mẫu có tên hỗ trợ tiếp cận. Nút lấy tên hỗ trợ tiếp cận từ nội dung hoặc giá trị của nút. Tất cả các chế độ điều khiển biểu mẫu khác đều yêu cầu phải có <label>
được liên kết. Nếu không có nhãn liên kết, trình duyệt vẫn sẽ hiển thị các thành phần điều khiển biểu mẫu, nhưng người dùng sẽ không biết thông tin nào được mong đợi.
Để liên kết rõ ràng một thành phần điều khiển biểu mẫu với <label>
, hãy thêm thuộc tính for
vào <label>
: giá trị là id
của thành phần điều khiển biểu mẫu được liên kết.
<label for="full_name">Your name</label>
<input type="text" id="full_name" name="name">
Việc liên kết nhãn với các thành phần điều khiển biểu mẫu có một số lợi ích. Nhãn giúp người dùng trình đọc màn hình sử dụng được các thành phần điều khiển biểu mẫu bằng cách cung cấp tên thành phần hỗ trợ tiếp cận. Nhãn cũng là "vùng nhấn"; chúng giúp trang web dễ sử dụng hơn cho những người dùng gặp vấn đề về sự khéo léo bằng cách tăng diện tích. Nếu bạn đang sử dụng chuột, hãy thử nhấp vào vị trí bất kỳ trên nhãn "Tên của bạn". Việc này sẽ đặt tiêu điểm nhập.
Để cung cấp nhãn ngầm ẩn, hãy đưa thành phần điều khiển biểu mẫu vào giữa thẻ mở và thẻ đóng <label>
. Bạn có thể truy cập vào thẻ này từ cả góc độ trình đọc màn hình và thiết bị con trỏ, nhưng thẻ này không cung cấp móc định kiểu như nhãn rõ ràng.
<label>Your name
<input type="text" name="name">
</label>
Vì nhãn là "khu vực nhấn", nên đừng đưa các phần tử tương tác vào nhãn rõ ràng hoặc bất kỳ thành phần tương tác nào khác ngoài thành phần điều khiển biểu mẫu được gắn nhãn trong nhãn ngầm ẩn. Ví dụ: nếu bạn đưa một đường liên kết vào nhãn, mặc dù trình duyệt sẽ hiển thị HTML, nhưng người dùng sẽ bị nhầm lẫn nếu họ nhấp vào nhãn để nhập một thành phần điều khiển biểu mẫu nhưng lại được chuyển hướng đến một trang mới.
Nhìn chung, <label>
xuất hiện trước phần điều khiển biểu mẫu, ngoại trừ trường hợp nút chọn và hộp đánh dấu. Đây không phải là yêu cầu bắt buộc.
Đây chỉ là mẫu trải nghiệm người dùng phổ biến. Loạt bài Tìm hiểu về biểu mẫu có thông tin về thiết kế biểu mẫu.
Đối với các nhóm nút chọn và hộp đánh dấu, nhãn cung cấp tên có thể truy cập cho thành phần điều khiển biểu mẫu được liên kết với nhóm đó; nhưng nhóm thành phần điều khiển và nhãn của các thành phần đó cũng cần có nhãn. Để gắn nhãn cho nhóm, hãy nhóm tất cả các phần tử vào một <fieldset>
, trong đó <legend>
cung cấp nhãn cho nhóm.
<fieldset>
<legend>Who is your favorite student?</legend>
<ul>
<li>
<label>
<input type="radio" value="blendan" name="machine"> Blendan Smooth
</label>
</li>
<li>
<label>
<input type="radio" value="hoover" name="machine"> Hoover Sukhdeep
</label>
</li>
<li>
<label>
<input type="radio" value="toasty" name="machine"> Toasty McToastface
</label>
</li>
</ul>
</fieldset>
Trong ví dụ này, <label>
ngầm ẩn mỗi nhãn gắn nhãn một nút chọn và <legend>
cung cấp nhãn cho nhóm nút chọn.
Việc lồng một <fieldset>
bên trong một <fieldset>
khác là một phương pháp tiêu chuẩn. Ví dụ: nếu biểu mẫu là một bản khảo sát gồm nhiều câu hỏi được chia thành các nhóm câu hỏi có liên quan, thì <fieldset>
"học sinh yêu thích" có thể được lồng vào một <fieldset>
khác có nhãn là "Yêu thích của bạn":
<fieldset>
<legend>Your favorites:</legend>
<ul start="6">
<li>
<fieldset>
<legend>Who is your favorite student?</legend>
<ul>
<li>
<!-- the rest of the code here -->
Giao diện mặc định của các phần tử này đã khiến chúng không được sử dụng đúng cách. Tuy nhiên, bạn có thể tạo kiểu cho <legend>
và <fieldset>
bằng CSS.
Ngoài tất cả các thuộc tính chung, <fieldset>
cũng hỗ trợ các thuộc tính name
, disabled
và form
.
Khi bạn tắt một fieldset, tất cả các thành phần điều khiển biểu mẫu lồng nhau sẽ bị tắt. Cả thuộc tính name
và form
đều không có nhiều tác dụng trên <fieldset>
. Bạn có thể sử dụng name
để truy cập vào nhóm trường bằng JavaScript, nhưng bản thân nhóm trường đó không có trong dữ liệu đã gửi (các thành phần điều khiển biểu mẫu có tên được lồng trong đó sẽ được đưa vào).
Loại phương thức nhập và bàn phím động
Như đã lưu ý trước đó, có 22 loại dữ liệu đầu vào.
Trong một số trường hợp, khi người dùng sử dụng thiết bị có bàn phím động chỉ hiển thị khi cần, chẳng hạn như điện thoại, thì kiểu bàn phím được sử dụng sẽ xác định loại bàn phím hiển thị. Bàn phím mặc định hiển thị có thể được tối ưu hoá cho loại phương thức nhập cần thiết.
Ví dụ: nhập tel
sẽ hiển thị bàn phím được tối ưu hoá để nhập số điện thoại; email
bao gồm @
và .
; và bàn phím động cho url
bao gồm dấu hai chấm và dấu gạch chéo. Rất tiếc, iPhone vẫn không bao gồm :
trong bàn phím động mặc định cho các loại dữ liệu đầu vào url
.
Bàn phím cho <input type="tel">
trên iPhone và hai điện thoại Android khác nhau:
Bàn phím cho <input type="email">
trên iPhone và hai điện thoại Android khác nhau:
Truy cập vào micrô và máy ảnh
Loại tệp nhập <input type="file">
cho phép tải tệp lên thông qua biểu mẫu. Tệp có thể thuộc bất kỳ loại nào, được xác định và giới hạn bằng thuộc tính accept
. Danh sách các loại tệp được chấp nhận có thể là danh sách đuôi tệp được phân tách bằng dấu phẩy, loại chung hoặc kết hợp các đuôi tệp và kiểu chung. Ví dụ: accept="video/*, .gif"
chấp nhận mọi tệp video hoặc gif động.
Sử dụng "audio/*
" cho tệp âm thanh, "video/*
" cho tệp video và "image/*
" cho tệp hình ảnh.
Bạn có thể sử dụng thuộc tính capture
được liệt kê trong thông số kỹ thuật ghi nội dung nghe nhìn nếu tệp nội dung nghe nhìn mới được tạo bằng máy ảnh hoặc micrô của người dùng. Bạn có thể đặt giá trị thành user
cho các thiết bị đầu vào hướng về phía người dùng hoặc environment
cho micrô hoặc máy ảnh sau của điện thoại. Nhìn chung, việc sử dụng capture
mà không có giá trị sẽ hoạt động vì người dùng sẽ chọn thiết bị đầu vào mà họ muốn sử dụng.
<label for="avatar">A recent photo of yourself:</label>
<input type="file" capture="user" accept="image/*" name="avatar" id="avatar">
Tính năng xác thực tích hợp
Xin nhắc lại, nếu không có JavaScript, HTML có thể ngăn việc gửi các biểu mẫu có giá trị không hợp lệ.
Có một số bộ chọn CSS khớp với các thành phần điều khiển biểu mẫu dựa trên sự hiện diện của các thuộc tính HTML, bao gồm :required
và :optional
nếu bạn đặt boolean required
hay không; :default
nếu checked
được mã hoá cứng; và :enabled
hoặc :disabled
, tuỳ thuộc vào việc phần tử có tương tác hay không và thuộc tính disabled
có xuất hiện hay không. Lớp giả :read-write
so khớp các phần tử với tập hợp contenteditable
và các thành phần điều khiển biểu mẫu có thể chỉnh sửa theo mặc định, chẳng hạn như các loại dữ liệu đầu vào number
, password
và text
(nhưng không phải hộp đánh dấu, nút chọn hoặc loại hidden
, v.v.). Nếu một phần tử thường có thể ghi có thuộc tính readonly
, thì phần tử đó sẽ khớp với :read-only
.
Khi người dùng nhập thông tin vào các thành phần điều khiển biểu mẫu, các bộ chọn giao diện người dùng CSS, bao gồm :valid
, :invalid
, :in-range
và :out-of-range
sẽ bật và tắt tuỳ thuộc vào trạng thái. Khi người dùng thoát khỏi một chế độ điều khiển biểu mẫu, lớp giả :user-invalid
hoặc :user-valid
chưa được hỗ trợ đầy đủ sẽ khớp.
Bạn có thể sử dụng CSS để đưa ra gợi ý về việc liệu các thành phần điều khiển biểu mẫu có bắt buộc và hợp lệ hay không khi người dùng tương tác với biểu mẫu. Bạn thậm chí có thể sử dụng CSS để ngăn người dùng nhấp vào nút gửi cho đến khi biểu mẫu hợp lệ:
form:invalid [type="submit"] {
opacity: 50%;
pointer-events: none;
}
Đoạn mã CSS này là một phản mẫu. Mặc dù giao diện người dùng của bạn có thể trực quan và rõ ràng, nhưng nhiều người dùng cố gắng gửi một biểu mẫu để bật thông báo lỗi. Việc ẩn nút gửi theo cách này sẽ không cho phép xác thực quy tắc ràng buộc, một tính năng mà nhiều người dùng dựa vào.
CSS đã áp dụng được cập nhật liên tục dựa trên trạng thái hiện tại của giao diện người dùng. Ví dụ: khi bạn thêm các loại dữ liệu đầu vào có các quy tắc ràng buộc, chẳng hạn như email
, number
, url
và loại ngày, nếu giá trị không phải là giá trị rỗng và giá trị hiện tại không phải là email, số, URL, ngày hoặc giờ hợp lệ, thì lớp giả CSS :invalid
sẽ khớp. Việc cập nhật liên tục này khác với việc xác thực quy tắc ràng buộc HTML tích hợp, chỉ xảy ra khi người dùng cố gắng gửi biểu mẫu.
Tính năng xác thực quy tắc ràng buộc tích hợp chỉ liên quan đến các quy tắc ràng buộc được đặt bằng thuộc tính HTML. Mặc dù bạn có thể tạo kiểu cho một phần tử dựa trên các lớp giả :required
và :valid
/:invalid
, nhưng trình duyệt đã cung cấp thông báo lỗi phát sinh từ các lỗi dựa trên các thuộc tính required
, pattern
, min
, max
và thậm chí là type
, khi gửi biểu mẫu.
Khi chúng ta cố gắng gửi biểu mẫu mà không chọn học sinh yêu thích bắt buộc, quy trình xác thực quy tắc ràng buộc sẽ ngăn việc gửi biểu mẫu do lỗi validityState.valueMissing
.
Nếu bất kỳ thuộc tính validityState
nào trả về true
, thì thao tác gửi sẽ bị chặn và trình duyệt sẽ hiển thị thông báo lỗi trong thành phần điều khiển biểu mẫu không chính xác đầu tiên, tập trung vào tiêu điểm. Khi người dùng kích hoạt một lượt gửi biểu mẫu và có các giá trị không hợp lệ, chế độ điều khiển biểu mẫu không hợp lệ đầu tiên sẽ hiển thị thông báo lỗi và nhận tiêu điểm. Nếu một thành phần điều khiển bắt buộc không được đặt giá trị, nếu giá trị số nằm ngoài phạm vi hoặc nếu giá trị không thuộc loại mà thuộc tính type
yêu cầu, thì biểu mẫu sẽ không xác thực, sẽ không gửi và thông báo lỗi sẽ xuất hiện.
Nếu giá trị number
, ngày hoặc giờ thấp hơn giá trị min
tối thiểu hoặc cao hơn giá trị max
tối đa, thì thành phần điều khiển sẽ là :out-of-range
(và :invalid
) và người dùng sẽ được thông báo về lỗi valididityState.rangeUnderflow
, validityState.rangeOverflow
khi họ cố gắng gửi biểu mẫu. Nếu giá trị không khớp với giá trị step
, cho dù được đặt rõ ràng hay đặt mặc định thành 1
, thì thành phần điều khiển sẽ là :out-of-range
(và :invalid
) và sẽ có lỗi validityState.stepMismatch
. Lỗi xuất hiện dưới dạng bong bóng trò chuyện và theo mặc định, sẽ cung cấp thông tin hữu ích về cách khắc phục lỗi.
Có các thuộc tính tương tự cho độ dài của giá trị: thuộc tính minlength
và maxlength
sẽ cảnh báo người dùng về lỗi bằng validityState.tooLong
hoặc validityState.tooShort
khi gửi.
maxlength
cũng ngăn người dùng nhập quá nhiều ký tự.
Việc sử dụng thuộc tính maxlength
có thể dẫn đến trải nghiệm người dùng kém. Nhìn chung, bạn nên cho phép người dùng nhập nhiều hơn số ký tự được phép bằng cách cung cấp một bộ đếm, tuỳ ý ở dạng phần tử <output>
không được gửi cùng với biểu mẫu, cho phép họ chỉnh sửa văn bản cho đến khi kết quả cho thấy không vượt quá độ dài tối đa được phép. Bạn có thể đưa maxlength
vào HTML; giống như mọi nội dung chúng ta đã thảo luận, maxlength
hoạt động mà không cần JavaScript. Sau đó, khi tải, giá trị của thuộc tính maxlength có thể được dùng để tạo bộ đếm ký tự này trong JavaScript.
Một số loại dữ liệu đầu vào có vẻ như có các quy tắc ràng buộc mặc định, nhưng thực tế lại không. Ví dụ: loại dữ liệu đầu vào tel
cung cấp bàn phím điện thoại số trên các thiết bị có bàn phím động, nhưng không ràng buộc các giá trị hợp lệ. Đối với loại dữ liệu đầu vào này và các loại dữ liệu đầu vào khác, có thuộc tính pattern
. Bạn có thể chỉ định một biểu thức chính quy mà giá trị cần khớp để được coi là hợp lệ.
Nếu một giá trị là chuỗi trống và giá trị đó không bắt buộc, thì giá trị đó sẽ không gây ra lỗi validityState.patternMismatch
. Nếu bắt buộc và trống, thông báo lỗi mặc định cho validityState.valueMissing
sẽ hiển thị cho người dùng thay vì patternMismatch
.
Đối với email, validityState.typeMismatch
có thể quá dễ tính đối với nhu cầu của bạn. Bạn nên thêm thuộc tính pattern
để các địa chỉ email nội bộ không có TLD sẽ không được chấp nhận là hợp lệ.
Thuộc tính mẫu cho phép cung cấp một biểu thức chính quy mà giá trị phải khớp. Khi yêu cầu khớp mẫu, hãy đảm bảo người dùng biết rõ kết quả mong đợi.
Bạn có thể thực hiện tất cả những việc này mà không cần một dòng JavaScript nào. Tuy nhiên, vì là một API HTML, bạn có thể sử dụng JavaScript để đưa vào thông báo tuỳ chỉnh trong quá trình xác thực quy tắc ràng buộc. Bạn cũng có thể sử dụng JavaScript để cập nhật số ký tự còn lại, hiển thị thanh tiến trình cho độ mạnh của mật khẩu hoặc bất kỳ cách nào khác để tích cực cải thiện tỷ lệ hoàn tất.
Ví dụ:
Ví dụ này có một biểu mẫu trong <dialog>
với <form>
lồng nhau có ba thành phần điều khiển biểu mẫu và hai nút gửi, với nhãn và hướng dẫn rõ ràng.
Nút gửi đầu tiên sẽ đóng hộp thoại. Sử dụng formmethod="dialog"
để ghi đè phương thức mặc định của biểu mẫu và đóng <dialog>
mà không gửi dữ liệu hoặc xoá dữ liệu đó. Bạn cũng phải thêm formnovalidate
, nếu không trình duyệt sẽ cố gắng xác thực bằng cách kiểm tra để đảm bảo rằng tất cả các trường bắt buộc đều có giá trị. Người dùng có thể muốn đóng hộp thoại và biểu mẫu mà không nhập bất kỳ dữ liệu nào; việc xác thực sẽ ngăn chặn việc này. Thêm aria-label="close"
vì "X" là một tín hiệu hình ảnh đã biết nhưng không phải là nhãn mô tả.
Các thành phần điều khiển biểu mẫu đều có nhãn ngầm định, nên bạn không cần thêm thuộc tính id
hoặc for
. Cả hai phần tử đầu vào đều có thuộc tính bắt buộc. Dữ liệu đầu vào số có step
được đặt rõ ràng để minh hoạ cách đưa step
vào. Vì step
mặc định là 1
, nên bạn có thể bỏ qua thuộc tính này.
<select>
có giá trị mặc định khiến thuộc tính required
không cần thiết. Thay vì đưa thuộc tính value
vào mỗi tuỳ chọn, giá trị mặc định sẽ là văn bản bên trong.
Nút gửi ở cuối sẽ đặt phương thức biểu mẫu thành POST. Khi được nhấp vào, tính hợp lệ của từng giá trị sẽ được kiểm tra. Nếu tất cả giá trị đều hợp lệ, dữ liệu biểu mẫu sẽ được gửi, hộp thoại sẽ đóng và trang có thể chuyển hướng đến thankyou.php
, là URL hành động. Nếu thiếu bất kỳ giá trị nào hoặc nếu giá trị số có bước không khớp hoặc nằm ngoài phạm vi, thì thông báo lỗi do trình duyệt liên quan xác định sẽ xuất hiện, biểu mẫu sẽ không được gửi và hộp thoại sẽ không đóng.
Bạn có thể tuỳ chỉnh thông báo lỗi mặc định bằng phương thức validityState.setCustomValidity('message here')
. Xin lưu ý rằng nếu bạn đặt thông báo tuỳ chỉnh, thì thông báo đó phải được đặt rõ ràng thành chuỗi trống khi mọi thông tin đều hợp lệ, nếu không biểu mẫu sẽ không gửi được.
Lưu ý khác
Có một phần dành riêng cho việc giúp người dùng nhập đúng dữ liệu vào biểu mẫu. Để có trải nghiệm người dùng tốt, điều quan trọng là ngăn người dùng mắc lỗi bằng cách bao gồm hướng dẫn và cung cấp gợi ý nếu cần. Mặc dù phần này đề cập đến cách chỉ riêng HTML có thể cung cấp tính năng xác thực phía máy khách, nhưng việc xác thực phải diễn ra ở cả phía máy khách và phía máy chủ. Bạn có thể cung cấp tính năng xác thực theo cách không gây khó chịu trong quá trình hoàn tất biểu mẫu, chẳng hạn như thêm dấu kiểm khi giá trị là chính xác. Tuy nhiên, đừng đưa ra thông báo lỗi trước khi quá trình kiểm soát biểu mẫu hoàn tất. Nếu người dùng thực sự mắc lỗi, hãy thông báo cho họ biết lỗi ở đâu và lỗi họ mắc phải.
Khi thiết kế biểu mẫu, bạn cần nhớ rằng có nhiều tiêu chuẩn về tên, định dạng địa chỉ và nhiều tiêu chuẩn khác trên khắp thế giới. Có người chỉ có một chữ cái làm họ (hoặc không có họ), không có mã zip, có địa chỉ đường phố gồm 3 dòng hoặc không có địa chỉ đường phố. Người này có thể đang xem phiên bản đã dịch của biểu mẫu.
Các thành phần điều khiển biểu mẫu, nhãn và thông báo lỗi phải hiển thị trên màn hình, chính xác và có ý nghĩa, xác định được theo phương thức lập trình và liên kết theo phương thức lập trình với phần tử hoặc nhóm biểu mẫu thích hợp. Bạn có thể và nên sử dụng thuộc tính autocomplete
để cho phép hoàn tất biểu mẫu nhanh hơn và cải thiện khả năng hỗ trợ tiếp cận.
HTML cung cấp tất cả các công cụ để tạo các thành phần điều khiển cơ bản của biểu mẫu. Một thành phần hoặc quy trình biểu mẫu càng có tính tương tác cao thì càng cần chú ý đến khả năng hỗ trợ tiếp cận đối với việc quản lý tiêu điểm, thiết lập và cập nhật tên, vai trò và giá trị của ARIA (nếu cần) cũng như thông báo trực tiếp của ARIA theo yêu cầu. Tuy nhiên, như chúng ta đã tìm hiểu ở đây, chỉ với HTML, bạn có thể đạt được mục tiêu về khả năng hỗ trợ tiếp cận và tính hợp lệ mà không cần sử dụng ARIA hoặc JavaScript.
Kiểm tra mức độ hiểu biết
Kiểm tra kiến thức của bạn về biểu mẫu.
Làm cách nào để các nút chọn thuộc cùng một nhóm?
id
.name
.Phần tử HTML nào được dùng để cho người dùng biết mục đích của trường biểu mẫu này?
<title>
<label>
<h1>