Forms

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

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

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

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

שליחת טפסים

הטפסים נשלחים כשהמשתמש מפעיל לחצן שליחה שמוצב בתוך הטופס. כשמשתמשים ב-<input> ללחצנים, 'value' הוא התווית של הלחצן והוא מוצג בלחצן. כשמשתמשים ב-<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>

בחירה באפשרות "הובר סוחדיפ" (או כל פעולה, בזמן שהדפדפן מוצג ולכן בוחר בערך האפשרות הראשונה כברירת מחדל) ולחיצה על לחצן השליחה תטען מחדש את הדף, ואז כתובת ה-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.

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

לחצני בחירה

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

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

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

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

כדי לטעון את הדף באמצעות אחד מלחצני הבחירה בקבוצה בעלת אותו שם שנבחרה, יש לכלול את המאפיין checked. לחצן הבחירה יתאים למעמד פסאודו-מחלקה :default של שירות CSS, גם אם המשתמש בחר רדיו אחר. לחצן הבחירה שנבחר תואם לסיווג הפסאודו :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>

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

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

בקבוצות של לחצני בחירה ותיבות סימון, התווית מספקת את השם הנגיש של פקד הטופס שאליו היא משויכת, אבל גם לקבוצת הפקדים ולתוויות שלהם נדרשת תווית. כדי לתייג את הקבוצה, צריך לקבץ את כל הרכיבים בתור <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. כשמשביתים קבוצת שדות, כל פקדי הטפסים המקוננים מושבתים. למאפיין name ולמאפיין form אין שימוש רב ב-<fieldset>. אפשר להשתמש ב-name כדי לגשת למערך השדות באמצעות JavaScript, אבל קבוצת השדות עצמה לא נכללת בנתונים שנשלחו (פקדי הטופס המופיעים בתוך קבוצת השדות נכללים).

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

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

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

מקלדת iPhone מציגה קלט type=tel. מקלדת Android מציגה קלט type=tel. מקלדת Android מציגה קלט type=tel.

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

מקלדת iPhone מציגה את סוג הקלט=אימייל. מקלדת Android מציגה סוג קלט=אימייל. מקלדת Android מציגה סוג קלט=אימייל.

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

סוג קלט הקובץ <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 אם הרכיב אינטראקטיבי.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 כך שכתובות אימייל אינטראנט ללא TLD לא יתקבלו כתקינות. מאפיין הדפוס מאפשר לספק ביטוי רגולרי שהערך שלו חייב להתאים לו. כאשר יש צורך בהתאמת דפוס, חשוב לוודא שלמשתמש ברור מאוד מה מצופה ממנו.

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

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

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

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

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

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

בדיקת ההבנה

בחינת הידע שלכם בטפסים.

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

צריך למקם את כולם בתוך מערך שדות.
אפשר לנסות שוב.
צריך לתת לכל כולן את אותו ערך מאפיין name.
נכון!
צריך לתת לכל כולן את אותו ערך מאפיין id.
אפשר לנסות שוב.

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

<h1>
אפשר לנסות שוב.
<title>
אפשר לנסות שוב.
<label>
נכון!