Forms

רוב האתרים והאפליקציות כוללים טופס אינטרנט. לאתרים עם בדיחות, כמו DoWebsitesצריךל בדיוקאותובבכלBrowser.com, יכול להיות שאין להם טופס כזה, אבל אפילו לאתר MachineLearningWorkshop.com (MLW), שמקורו בבדיחה באחד באפריל, יש צורה, אבל לא מזויפת. ה"קריאה לפעולה" הראשית של MLW היא טופס רישום למכונה להירשם לסדנה. הטופס הזה נמצא ברכיב <form>.

הרכיב HTML <form> מזהה ציון דרך במסמך שמכיל אמצעי בקרה אינטראקטיביים לשליחת מידע. בתוך <form> נמצאים כל הפקדים האינטראקטיביים (והלא אינטראקטיביים) בטופס.

ל-HTML יש יכולות רבות. הקטע הזה מתמקד ביכולות של HTML, ומסביר מה אפשר לעשות עם HTML בלי להוסיף JavaScript. שימוש בנתוני טפסים בצד הלקוח כדי לעדכן את ממשק המשתמש בדרך כלשהי כרוך בדרך כלל ב-CSS או ב-JavaScript, שאינם נידונים כאן. יש קורס שלם בנושא Learn Forms. לא נציג כאן את הקטע הזה, אבל נציג כמה אמצעי בקרה בטפסים ואת מאפייני ה-HTML שמאפשרים להם לפעול.

בעזרת טפסים, אתם יכולים לאפשר למשתמשים לקיים אינטראקציה עם האתר או האפליקציה שלכם, לאמת את המידע שהוזן ולשלוח את הנתונים לשרת. מאפייני HTML יכולים לחייב את המשתמש לבחור פקדי טופס או להזין ערך. מאפייני HTML יכולים להגדיר קריטריונים ספציפיים שהערך צריך לעמוד בהם כדי להיות חוקי. כשהמשתמש מנסה לשלוח את הטופס, כל הערכים של בקרת הטופס עוברים אימות אילוצים בצד הלקוח ויכולים למנוע את השליחה עד שהנתונים עומדים בקריטריונים הנדרשים, וכל זה בלי JavaScript. אפשר גם להשבית את התכונה הזו: הגדרת המאפיין novalidate ב-<form> או, לרוב, ב-formnovalidate בלחצן, שמאפשרת לשמור את נתוני הטופס ולהשלים אותם מאוחר יותר, מונעת את האימות.

שליחת טפסים

הטפסים נשלחים כשהמשתמש מפעיל לחצן שליחה שנמצא בתוך הטופס. כשמשתמשים ב-<input> ללחצנים, הערך הוא התווית של הלחצן והוא מוצג בלחצן. כשמשתמשים ב-<button>, התווית היא הטקסט שבין התג הפותח לבין התג הסוגר של <button>. אפשר לכתוב לחצן שליחה בשתי דרכים:

<input type="submit" value="Submit Form">
<button type="submit">Submit Form</button>

לטופס פשוט מאוד, צריך רכיב <form> עם כמה רכיבי קלט של טופס ועם לחצן שליחה. עם זאת, יש עוד דברים שצריך לדעת על שליחת טופס.

המאפיינים של הרכיב <form> מגדירים את שיטת ה-HTTP שבאמצעותה הטופס נשלח ואת כתובת ה-URL שמעבדת את שליחת הטופס. כן, אפשר לשלוח טפסים, לעבד אותם ולטעון דף חדש בלי JavaScript. האלמנט <form> הוא כל כך חזק.

ערכי המאפיינים action ו-method של האלמנט <form> מגדירים את כתובת ה-URL שמעבדת את נתוני הטופס ואת שיטת ה-HTTP שמשמשת לשליחת הנתונים, בהתאמה. כברירת מחדל, נתוני הטופס נשלחים לדף הנוכחי. אחרת, מגדירים את המאפיין action לכתובת ה-URL שאליה צריך לשלוח את הנתונים.

הנתונים שנשלחים מורכבים מצמדים של שם/ערך של אמצעי הבקרה השונים בטופס. כברירת מחדל, הרשימה הזו כוללת את כל פקדי הטופס שמוטמעים בתוך הטופס וכוללים את הערך name. עם זאת, באמצעות המאפיין form אפשר לכלול פקדי טפסים מחוץ ל-<form> ולהשמיט פקדי טפסים שמוצבים בתוך <form>. המאפיין form נתמך בפקדי טפסים וב-<fieldset>, והערך שלו הוא id של הטופס שאליו משויך הפקד, ולא בהכרח של הטופס שבו הוא מוטמע. המשמעות היא שאין צורך להטמיע פיזית את אמצעי הבקרה של הטפסים ב-<form>.

המאפיין method מגדיר את פרוטוקול ה-HTTP של הבקשה: בדרך כלל GET או POST. עם הערך GET, נתוני הטופס נשלחים כמחרוזת פרמטר של name=value זוגות, המצורף לכתובת ה-URL של action.

באמצעות POST, הנתונים מתווספים לגוף של בקשת ה-HTTP. כששולחים נתונים מאובטחים, כמו סיסמאות ופרטי כרטיס אשראי, תמיד צריך להשתמש ב-POST.

יש גם שיטה DIALOG. אם <form method="dialog"> נמצא בתוך <dialog>, שליחת הטופס תסגור את תיבת הדו-שיח. מתרחש אירוע שליחה, אבל הנתונים לא נמחקים ולא נשלחים. שוב, בלי JavaScript. אפשר לקרוא על כך בקטע על תיבת הדו-שיח. חשוב לזכור שהפעולה הזו לא שולחת את הטופס, לכן מומלץ לכלול את formmethod="dialog" וגם את formnovalidate בלחצן השליחה.

לחצני טופס יכולים לכלול יותר מהמאפיינים שמפורטים בתחילת הקטע הזה. אם הלחצן כולל את המאפיין formaction, formenctype, formmethod, formnovalidate או formtarget, הערכים שמוגדרים בלחצן שמפעיל את שליחת הטופס מקבלים קדימות על פני הערכים action, enctype, method ו-target המוגדרים ב-<form>. אימות האילוצים מתבצע לפני שליחת הטופס, אבל רק אם לא מופיע הערך formnovalidate בלחצן שליחת הטופס הפעיל או הערך novalidate ב-<form>.

כדי לתעד את הלחצן ששימש לשליחת טופס, מציינים את הערך name. לחצנים ללא שם או ערך לא נשלחים עם נתוני הטופס בזמן שליחת הטופס.

אחרי שליחת הטופס

כשהמשתמש שולח טופס אונליין שהושלם, השמות והערכים של אמצעי הבקרה הרלוונטיים בטופס נשלחים. השם הוא הערך של המאפיין name. הערכים מגיעים מהתוכן של המאפיין value או מהערך שהמשתמש הזין או בחר. הערך של <textarea> הוא הטקסט הפנימי שלו. הערך של <select> הוא value של <option> שנבחר, או אם ה-<option> לא כולל מאפיין value, הערך הוא הטקסט הפנימי של האפשרות שנבחרה.

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

אם בוחרים באפשרות 'Hoover Sukhdeep' (או לא עושים כלום, כי הדפדפן מציג את ערך האפשרות הראשונה ולכן בוחר בו כברירת מחדל) ואז לוחצים על לחצן השליחה, הדף הזה יטען מחדש עם כתובת ה-URL הבאה:

https://web.dev/learn/html/forms?student=hoover

מכיוון שלאפשרות השנייה אין מאפיין value, הטקסט הפנימי נשלח כערך. בחירה באפשרות 'Blendan Smooth' ולחיצה על לחצן השליחה תטען מחדש את הדף הזה, וכתובת ה-URL תהיה:

https://web.dev/learn/html/forms?student=Blendan+Smooth

כששולחים טופס, המידע שנשלח כולל את השמות והערכים של כל אמצעי הבקרה של הטפסים שיש להם name, מלבד תיבות סימון שלא מסומנות, לחצני רדיו שלא מסומנים, והשמות והערכים של כל הלחצנים מלבד הלחצן ששלח את הטופס. בכל שאר אמצעי הבקרה בטופס, אם לאמצעי הבקרה בטופס יש שם אבל לא הוזן ערך או שהוגדר ערך ברירת מחדל, הערך של name של אמצעי הבקרה בטופס נשלח כערך ריק.

יש 22 סוגים של קלט, ולכן אי אפשר להתייחס לכולם. חשוב לזכור שאפשר לכלול ערך, אבל בדרך כלל לא מומלץ לעשות זאת כשרוצים שהמשתמש יזין מידע. ברכיבי <input> שבהם המשתמש לא יכול לערוך את הערך, תמיד צריך לכלול ערך, כולל ברכיבי קלט מסוג hidden,‏ radio,‏ checkbox,‏ submit,‏ button ו-reset.

מומלץ להשתמש ב-names ייחודיים לפקדי טפסים כדי לפשט את עיבוד הנתונים בצד השרת. תיבות סימון ולחצני רדיו הם יוצאי דופן לכלל הזה.

לחצני בחירה

אם שמתם לב פעם שכאשר בוחרים לחצן בחירה בתוך קבוצה של לחצני בחירה, ניתן לבחור רק אחד בכל פעם, הסיבה לכך היא המאפיין name. האפקט היחיד הזה נוצר על ידי מתן את אותו name לכל לחצן בחירה בקבוצה.

הערך של name צריך להיות ייחודי לקבוצה: אם משתמשים בטעות באותו name בשתי קבוצות נפרדות, לחיצה על לחצן רדיו בקבוצה השנייה תבטל את הבחירה שבוצעה בקבוצה הראשונה עם אותו name.

הערך של name יחד עם הערך של value של לחצן הבחירה שנבחר נשלחים עם הטופס. חשוב לוודא שלכל לחצן בחירה יש value רלוונטי (ובדרך כלל ייחודי). הערכים של לחצני הבחירה שלא נבחרו לא נשלחים.

אפשר ליצור בדף כמה קבוצות רדיו שרוצים, וכל קבוצה פועלת בנפרד, כל עוד לכל אחת מהן יש name ייחודי לקבוצה.

אם רוצים לטעון את הדף עם אחד מלחצני הבחירה בקבוצה בעלת אותו שם שנבחרה, צריך לכלול את המאפיין checked. לחצן הבחירה הזה יתאים לפסאודו-סיווג CSS‏ :default, גם אם המשתמש יבחר לחצן אחר. לחצן הבחירה הנוכחי תואם למחלקה המדומה :checked.

אם המשתמש נדרש לבחור שלט בחירה מתוך קבוצה של לחצני בחירה, מוסיפים את המאפיין required לפחות לאחד מהפקדים. אם כוללים את הערך required בלחצן בחירה בקבוצה, חובה לבחור אפשרות לשליחת טופס, אבל זה לא חייב להיות רדיו עם המאפיין שנבחר כדי להיות חוקי. בנוסף, צריך לציין בבירור ב-<legend> שאמצעי הבקרה בטופס נדרש. בהמשך מוסבר איך לתייג קבוצות של לחצני בחירה יחד עם כל לחצן בנפרד.

תיבות סימון

לכל התיבות הסימון בקבוצה יכול להיות אותו name. אפשר לשלוח את הטופס name ו-value רק בתיבות סימון נבחרות. אם בחרתם כמה תיבות סימון עם אותו שם, אותו שם יישלח עם ערכים שונים (אנחנו מקווים). אם יש לכם כמה אמצעי בקרה בטופס עם אותו שם, גם אם לא כולם תיבות סימון, כולם יישלחו, מופרדים על ידי סימני &.

אם לא תכללו את value בתיבה מסוימת, הערך של התיבות שנבחרו יהיה on כברירת מחדל, וזה לא מועיל בדרך כלל. אם יש לכם שלוש תיבות סימון בשם chk וכולן מסומנות, לא ניתן יהיה לפענח את שליחת הטופס:

https://web.dev/learn/html/forms?chk=on&chk=on&chk=on

כדי להגדיר תיבה לבחירה כחובה, מוסיפים את המאפיין required. תמיד צריך להודיע למשתמש מתי צריך לסמן תיבת סימון או מתי צריך להשתמש בכל אמצעי בקרה בטופס. כשמוסיפים את required לתיבת סימון, תיבת הסימון הזו נדרשת בלבד. היא לא משפיעה על תיבות סימון אחרות באותו שם.

תוויות ומערכי שדות

כדי שהמשתמשים ידעו איך למלא טופס, צריך להבטיח שהוא נגיש. לכל אמצעי בקרה בטופס צריכה להיות תווית. מומלץ גם להוסיף תוויות לקבוצות של פקדי טפסים. אזורים נפרדים של קלט, בחירה וטקסט מסומנים בתווית <label>, אבל קבוצות של רכיבי בקרה בטופס מסומנות לפי התוכן של <legend> של <fieldset> שמקבץ אותם.

יכול להיות ששמתם לב שבדוגמאות הקודמות, לכל אמצעי הבקרה בטופס, מלבד לחצן השליחה, היה <label>. תוויות מספקות שמות נגישים לפקדי טפסים. השם הנגיש של הלחצנים נגזר מהתוכן או מהערך שלהם. לכל שאר פקדי הטופס צריך להיות <label> משויך. אם אין תווית משויכת, הדפדפן עדיין יבצע את פקדי הטופס אבל המשתמשים לא יידעו איזה מידע מצופה.

כדי לשייך באופן מפורש רכיב של טופס ל-<label>, צריך לכלול את המאפיין for ב-<label>: הערך הוא id של רכיב הטופס שאליו הוא משויך.

<label for="full_name">Your name</label>
<input type="text" id="full_name" name="name">

יש כמה יתרונות לשיוך תוויות לאמצעי הבקרה בטופס. תוויות מאפשרות למשתמשים בקורא מסך להשתמש בפקדי טפסים, על ידי מתן שם נגיש לפקדים. תוויות הן גם 'אזורי מגע'. הן מגדילות את האזור ומאפשרות למשתמשים עם בעיות במיומנות להשתמש באתר בקלות רבה יותר. אם אתם משתמשים בעכבר, נסו ללחוץ במקום כלשהו על התווית 'השם שלך'. הפעולה הזו מעבירה את המיקוד לקלט.

כדי לספק תוויות משתמעות, צריך לכלול את רכיב הטופס בין התגים <label> הפותחים והסוגרים. אפשר לגשת אליה באותה מידה גם מקורא המסך וגם מנקודת המבט של מכשיר המצביע, אבל היא לא מספקת את התוכן המושך כמו התווית המפורשת.

<label>Your name
  <input type="text" name="name">
</label>

מכיוון שתוויות הן &#39;אזורי היעד&#39;, אסור לכלול אלמנטים אינטראקטיביים בתוך תווית מפורשת, או רכיבים אינטראקטיביים אחרים מלבד רכיב הבקרה של הטופס המתויג בתווית משתמעת. לדוגמה, אם תכללו קישור בתווית, בזמן שהדפדפן יבצע את עיבוד ה-HTML, המשתמשים עלולים להתבלבל אם הם ילחצו על התווית כדי להיכנס לפקד ליצירת טופס, אבל יופנו לדף חדש.

בדרך כלל, <label> מופיע לפני פקד הטופס, חוץ מאשר במקרים של לחצני בחירה ותיבות סימון. לא חובה לעשות זאת. זהו רק דפוס UX נפוץ. בסדרת המאמרים 'מידע על טפסים' יש מידע על עיצוב טפסים.

בקבוצות של לחצני רדיו ותיבות סימון, התווית מספקת את השם הנגיש של רכיב הטופס שאליו היא משויכת. עם זאת, גם לקבוצת הרכיבים ולתוויות שלהם צריכה להיות תווית. כדי לתייג את הקבוצה, צריך לקבץ את כל הרכיבים ל-<fieldset>, כאשר ה-<legend> מספק את התווית של הקבוצה.

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

בדוגמה הזו, כל אחד מה-<label>ים המשתמעים מתייחס לתווית של לחצן הבחירה, וה-<legend> מספק את התווית של קבוצת לחצני הבחירה. שימוש ב-<fieldset> בתוך <fieldset> אחר הוא שיטה רגילה. לדוגמה, אם טופס הוא סקר עם הרבה שאלות שחולקות לקבוצות של שאלות קשורות, יכול להיות שהשדה <fieldset> 'התלמיד/ה המועדף/ת' יופיע בתוך <fieldset> אחר עם התווית 'המועדפים שלך':

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

המראה של הרכיבים האלה כברירת מחדל הוביל לשימוש מועט בהם, אבל אפשר לסגנן את <legend> ואת <fieldset> באמצעות CSS. בנוסף לכל המאפיינים הגלובליים, <fieldset> תומך גם במאפיינים name,‏ disabled ו-form. כשמשביתים fieldset, כל פקדי הטפסים שמוטמעים בתוך fieldset מושבתים. אין שימוש רב במאפיינים name ו-form ב-<fieldset>. אפשר להשתמש ב-name כדי לגשת ל-fieldset באמצעות JavaScript, אבל ה-fieldset עצמו לא נכלל בנתונים שנשלחים (אמצעי הבקרה של הטפסים ששמות ניתנו להם, שמוטמעים בתוך ה-fieldset, נכללים).

סוגי קלט ומקלדת דינמית

כפי שצוין קודם, יש 22 סוגים שונים של קלט. במקרים מסוימים, כשמשתמש משתמש במכשיר עם מקלדת דינמית שמוצגת רק לפי הצורך, כמו טלפון, סוג הקלט שבו נעשה שימוש קובע את סוג המקלדת שמוצגת. אפשר לבצע אופטימיזציה של מקלדת ברירת המחדל שמוצגת בהתאם לסוג הקלט הנדרש. לדוגמה, מקלידים tel כדי להציג מקלדת שמתאימה להזנת מספרי טלפון. מקלידים email כדי להציג את המקש @ ואת המקש .. המקלדת הדינמית של url כוללת את התו פסיק ואת התו קו נטוי. לצערנו, עדיין אין אפשרות להזין את התו : במקלדת הדינמית שמוגדרת כברירת מחדל לסוגי הקלט url ב-iPhone.

מקלדות ל-<input type="tel"> ב-iPhone ובשני טלפונים שונים עם Android:

מקלדת iPhone שמוצג בה input type=tel. מקלדת Android שמוצג בה קלט מסוג type=tel. מקלדת Android שמוצג בה קלט מסוג type=tel.

מקלדות של <input type="email"> ב-iPhone ובשני טלפונים שונים עם Android:

מקלדת iPhone שמוצג בה input type=email. מקלדת Android מציגה את סוג הקלט=email. מקלדת Android שמוצג בה input type=email.

גישה למיקרופון ולמצלמה

סוג הקלט של הקובץ <input type="file"> מאפשר העלאת קבצים באמצעות טפסים. הקבצים יכולים להיות מכל סוג, ומוגדרים ומוגבלים על ידי המאפיין accept. רשימת סוגי הקבצים הקבילים יכולה להיות רשימה של סיומות קבצים שמופרדות בפסיקים, סוג גלובלי או שילוב של סוגים ותוספים גלובליים. לדוגמה, accept="video/*, .gif" מקבל כל קובץ וידאו או קובץ GIF מונפש. משתמשים ב-'audio/*' לקובצי אודיו, ב-'video/*' לקובצי וידאו וב-'image/*' לקובצי תמונות.

אפשר להשתמש במאפיין המנומר capture, שמוגדר במפרט של צילום מדיה, אם רוצים ליצור קובץ מדיה חדש באמצעות המצלמה או המיקרופון של המשתמש. אפשר להגדיר את הערך כ-user למכשירי הקלט שמוצגים למשתמש, או כ-environment למצלמה האחורית או למיקרופון של הטלפון. באופן כללי, השימוש ב-capture בלי ערך עובד כי המשתמש בוחר את מכשיר הקלט שבו הוא רוצה להשתמש.

<label for="avatar">A recent photo of yourself:</label>
<input type="file" capture="user" accept="image/*" name="avatar" id="avatar">

אימות מובנה

שוב, בלי לכלול JavaScript, HTML יכול למנוע שליחה של טפסים עם ערכים לא חוקיים.

יש סלקטורים מסוימים ב-CSS שתואמים לאמצעי הבקרה בטופס על סמך נוכחות של מאפייני HTML, כולל :required ו-:optional אם הערך הבוליאני required מוגדר או לא; :default אם checked מקודד באופן קבוע; ו-:enabled או :disabled, בהתאם לכך שהרכיב אינטראקטיבי ושהמאפיין disabled נוכח. פסאודו-הקלאס :read-write תואם לאלמנטים עם ההגדרה contenteditable ולפקדי טפסים שניתנים לעריכה כברירת מחדל, כמו סוגי הקלט number,‏ password ו-text (אבל לא תיבות סימון, לחצני בחירה או הסוג hidden, בין היתר). אם לאלמנט שאפשר לכתוב בו בדרך כלל מוגדר המאפיין readonly, הוא יתאים במקום זאת ל-:read-only.

כשהמשתמש מזין מידע באמצעי הבקרה בטופס, הסלקטורים של ממשק המשתמש ב-CSS, כולל :valid,‏ :invalid,‏ :in-range ו-:out-of-range, יופעלו ויושבת בהתאם למצב. כשהמשתמש יוצא מאמצעי בקרה בטופס, תתבצע התאמה לפסאודו-סיווג :user-invalid או ל-:user-valid, שעדיין אין תמיכה מלאה בו.

אתם יכולים להשתמש ב-CSS כדי לספק רמזים לגבי הצורך ברכיבי הבקרה של הטופס והתוקף שלהם בזמן שהמשתמש מבצע פעולות בטופס. אפשר אפילו להשתמש ב-CSS כדי למנוע ממשתמשים ללחוץ על לחצן השליחה עד שהטופס תקין:

form:invalid [type="submit"] {
  opacity: 50%;
  pointer-events: none;
}

קטע הקוד הזה של CSS הוא דפוס שלילי. יכול להיות שממשק המשתמש נראה אינטואיטיבי וברור, אבל משתמשים רבים מנסים לשלוח טופס כדי להפעיל את שליחת הודעות השגיאה. הגדרת לחצן שליחה מושבת באופן הזה לא מאפשרת אימות אילוצים, תכונה שמשתמשים רבים מסתמכים עליה.

קוד ה-CSS שהוחל מתעדכן באופן שוטף על סמך המצב הנוכחי של ממשק המשתמש. לדוגמה, כשכוללים סוגי קלט עם אילוצים, כמו email,‏ number,‏ url וסוגים של תאריכים, אם הערך הוא לא null (לא ריק) והערך הנוכחי הוא לא כתובת אימייל, מספר, כתובת URL, תאריך או שעה תקינים, הפסאודו-סיווג :invalid ב-CSS יתאים. העדכון המתמיד הזה שונה מאימות אילוצים מובנה ב-HTML, שמתרחש רק כשהמשתמש מנסה לשלוח את הטופס.

אימות האילוצים המובנה רלוונטי רק לאילוצים שהוגדרו באמצעות מאפייני HTML. אפשר לעצב רכיב על סמך פסאודו-הקלאסות :required ו-:valid/:invalid, אבל הודעות השגיאה שסופקו על ידי הדפדפן נובעות משגיאות שמבוססות על המאפיינים required,‏ pattern,‏ min,‏ max ואפילו type, והן מופיעות בזמן שליחת הטופס.

הודעת שגיאה שמציינת שצריך להוסיף שדה עם מספר אפשרויות בחירה.

כשמנסים לשלוח את הטופס בלי לבחור את התלמיד/ה האהוב/ה הנדרש/ת, אימות האילוצים מונע שליחת הטופס בגלל שגיאה מסוג validityState.valueMissing.

אם אחד מהמאפיינים validityState מחזיר את הערך true, השליחה חסומה והדפדפן מציג הודעת שגיאה ברכיב הבקרה הראשון בטופס שגוי, ומעביר אליו את המיקוד. כשהמשתמש מפעיל שליחת טופס ויש ערכים לא חוקיים, הודעת השגיאה תוצג ברכיב הבקרה הראשון של הטופס שלא חוקי, והמיקוד יועבר אליו. אם לא הוגדר ערך לבקרה נדרשת, אם ערך מספרי הוא מחוץ לטווח או אם הערך אינו מהסוג שנדרש על ידי המאפיין type, הטופס לא יאומת ולא יישלח, ותוצג הודעת שגיאה.

אם הערך של number, התאריך או השעה נמוך מהערך המינימלי min או גבוה מהערך המקסימלי max, הסטטוס של הרכיב יהיה :out-of-range (וגם :invalid), והמשתמש יקבל הודעה על השגיאה valididityState.rangeUnderflow, validityState.rangeOverflow כשינסו לשלוח את הטופס. אם הערך לא תואם לערך של step, בין שהוגדר במפורש ובין שהוגדר כברירת מחדל כ-1, אמצעי הבקרה יהיה :out-of-range (וגם :invalid) ותופיע השגיאה validityState.stepMismatch. השגיאה מופיעה כבועה, ומציגה כברירת מחדל מידע שימושי על תיקון הטעות.

יש מאפיינים דומים לאורך הערכים: המאפיינים minlength ו-maxlength יתריעו למשתמש על שגיאה עם הערך validityState.tooLong או validityState.tooShort בזמן השליחה. הרכיב maxlength גם מונע מהמשתמש להזין יותר מדי תווים.

שימוש במאפיין maxlength עלול לפגוע בחוויית המשתמש. באופן כללי, מומלץ לאפשר למשתמש להזין יותר מהאורך המרבי של התווים, ולצרף ספירה לאחור. אפשר להשתמש ברכיב <output>, שלא נשלח עם הטופס, כדי לאפשר למשתמש לערוך את הטקסט עד שהפלט מראה שלא חרג מהאורך המרבי המותרת. אפשר לכלול את maxlength ב-HTML. כמו כל מה שדיברנו, הוא פועל בלי JavaScript. לאחר הטעינה, ניתן להשתמש בערך של המאפיין maxlength כדי ליצור את מונה התווים הזה ב-JavaScript.

נראה שלסוגי קלט מסוימים יש אילוצים שמוגדרים כברירת מחדל, אבל אין להם. לדוגמה, סוג הקלט tel מאפשר להשתמש במקלדת טלפונית מספרית במכשירים עם מקלדות דינמיות, אבל לא מגביל את הערכים התקפים. למאפיין הזה ולסוגי קלט אחרים יש את המאפיין pattern. אפשר לציין ביטוי רגולרי שהערך צריך להתאים לו כדי להיחשב תקין. אם הערך הוא מחרוזת ריקה והערך לא נדרש, הוא לא יגרום לשגיאה מסוג validityState.patternMismatch. אם צריך להשאיר את השדה ריק, הודעת השגיאה שמוגדרת כברירת מחדל תוצג למשתמש עבור validityState.valueMissingבמקום patternMismatch.

לאימיילים, כנראה שה-validityState.typeMismatch גמיש מדי לצרכים שלכם. מומלץ לכלול את המאפיין pattern כדי שכתובות אימייל של אינטראנט ללא דומיין ברמה העליונה לא יתקבלו כתקינות. מאפיין הדפוס מאפשר לספק ביטוי רגולרי שהערך חייב להתאים לו. כשמחייבים התאמת תבניות, חשוב לוודא שלמשתמשים יהיה ברור מאוד מה מצופה מהם.

אפשר לעשות את כל זה בלי שורת JavaScript אחת, אבל מכיוון שמדובר ב-HTML API, אפשר להשתמש ב-JavaScript כדי לכלול הודעות בהתאמה אישית במהלך אימות האילוצים. אפשר גם להשתמש ב-JavaScript כדי לעדכן את מספר התווים שנותרו, להציג סרגל התקדמות לחוזק הסיסמה או כל מספר דרכים אחר לשיפור ההשלמה האוטומטית.

דוגמה

בדוגמה הזו יש טופס בתוך <dialog> עם <form> בתצוגת עץ, עם שלושה רכיבי בקרה בטופס ושני לחצני שליחה, עם תוויות והוראות ברורות.

לחצן השליחה הראשון סוגר את תיבת הדו-שיח. משתמשים ב-formmethod="dialog" כדי לשנות את שיטת ברירת המחדל של הטופס, וסוגרים את <dialog> בלי לשלוח את הנתונים או למחוק אותם. צריך לכלול גם את formnovalidate, אחרת הדפדפן ינסה לאמת את הבקשה על ידי בדיקה של כל השדות הנדרשים שיש להם ערך. יכול להיות שהמשתמש ירצה לסגור את תיבת הדו-שיח ואת הטופס בלי להזין נתונים. אימות ימנע זאת. צריך לכלול את aria-label="close" כי X הוא סימן חזותי ידוע, אבל הוא לא תווית תיאורית.

לכל אמצעי הבקרה בטופס יש תוויות משתמעות, כך שאין צורך לכלול את המאפיינים id או for. שני אלמנטי הקלט מכילים את המאפיין הנדרש, ולכן הם נדרשים. הקלט של המספר מוגדר במפורש כ-step כדי להדגים איך step נכלל. כברירת מחדל, הערך של step הוא 1, לכן אפשר להשמיט את המאפיין הזה.

למאפיין <select> יש ערך ברירת מחדל, ולכן אין צורך במאפיין required. במקום לכלול את המאפיין value בכל אפשרות, הערך שמוגדר כברירת מחדל הוא הטקסט הפנימי.

לחצן השליחה בסוף מגדיר את שיטת הטפסים כ-POST. כשלוחצים עליו, מתבצעת בדיקה של תקינות כל הערכים. אם כל הערכים תקינים, נתוני הטופס יישלחו, תיבת הדו-שיח תיסגר והדף עשוי להפנות לכתובת ה-URL של הפעולה, thankyou.php. אם חסרים ערכים, אם הערך המספרי לא תואם לשלב או שהוא מחוץ לטווח, תוצג הודעת שגיאה רלוונטית שהוגדרה בדפדפן, הטופס לא יישלח והתיבת הדו-שיח לא תיסגר. אפשר להתאים אישית את הודעות השגיאה שמוגדרות כברירת מחדל באמצעות ה-method validityState.setCustomValidity('message here'). חשוב לזכור: אם מגדירים הודעה מותאמת אישית, צריך להגדיר את ההודעה במפורש למחרוזת הריקה כשהכול תקין, אחרת הטופס לא יישלח.

שיקולים נוספים

יש קטע שלם שמקדיש לעזרה למשתמשים להזין את הנתונים הנכונים בטפסים. כדי לשפר את חוויית המשתמש, חשוב למנוע ממשתמשים לבצע שגיאות על ידי הכללת הוראות ושימוש בטיפים לפי הצורך. בקטע הזה נסביר איך HTML בלבד יכול לספק אימות בצד הלקוח, אבל חשוב לזכור שצריך לבצע אימות גם בצד הלקוח וגם בצד השרת. אפשר לספק תיקוף בדרכים לא פולשניות במהלך מילוי הטופס, למשל הוספת סימן וי כאשר הערך נכון. עם זאת, אין להציג הודעות שגיאה לפני שהשליטה בטופס הושלמה. אם המשתמש טועה, צריך ליידע אותו איפה נמצאת הטעות ומה הוא טעה.

כשמעצבים טפסים, חשוב לזכור שיש ברחבי העולם סטנדרטים שונים לגבי שמות, פורמטים של כתובות ועוד. למישהו יכולה להיות אות אחת בתור שם משפחה (או ללא שם משפחה בכלל), לא יכול להיות מיקוד, כתובת עם שלוש שורות או רחוב, או כתובת. יכול להיות לאדם הזה מוצגת גרסה מתורגמת של הטופס שלך.

פקדי הטופס, התוויות שלהם והודעות השגיאה צריכים להיות גלויים במסך, מדויקים ומשמעותיים, ניתנים לקביעה באופן פרוגרמטי, ומשויכים באופן פרוגרמטי לרכיב הטופס או לקבוצה המתאימים. אפשר להשתמש במאפיין autocomplete כדי לאפשר מילוי מהיר יותר של טפסים ולשפר את הנגישות.

ב-HTML יש את כל הכלים שדרושים כדי להפוך את אמצעי הבקרה הבסיסיים בטופס לנגישים. ככל שרכיב או תהליך הם אינטראקטיביים יותר, כך צריך להקדיש יותר תשומת לב לנגישות של ניהול ממוקד, הגדרה ועדכון של שמות, תפקידים וערכים של ARIA (לפי הצורך), והודעות בשידור חי של ARIA לפי הצורך. עם זאת, כפי שלמדנו כאן, אפשר להגיע ליעדים של נגישות ותאימות באמצעות HTML בלבד, בלי להשתמש ב-ARIA או ב-JavaScript.

בדיקת ההבנה

בודקים את הידע שלכם בנושא טפסים.

איך גורמים לכך שלחצני הבחירה יהיו חלק מאותה קבוצה?

צריך להקצות לכל הפריטים את אותו ערך למאפיין name.
צריך להכניס את כולם לתוך fieldset.
צריך להקצות לכל הפריטים את אותו ערך למאפיין id.

איזה רכיב HTML משמש כדי להסביר למשתמש למה מיועד שדה הטופס הזה?

<title>
<label>
<h1>