איך יוצרים טופס ב-HTML
טופס הוא אלמנט <form> שמכיל שדות וכפתור שליחה. כל שדה צריך name: זה המפתח שתחתיו הערך נשלח. מלאו את הטופס ולחצו על Send. התצוגה המקדימה לא שולחת שום דבר לשום מקום; היא מציגה בדיוק מה הדפדפן היה שולח.
החלקים:
actionהוא הכתובת שאליה הנתונים הולכים, ו-methodהוא האופן (כאןpost).nameעל כל שדה. הערך שלו הוא מה שהקורא הקליד.<label>נותן שם לכל שדה על המסך ועבור קוראי מסך (ראו HTML label).requiredו-type="email"גורמים לדפדפן לבדוק את השדות לפני השליחה. נסו לשלוח עם שם ריק, או עםabcבתור אימייל.- כפתור השליחה שולח את הטופס. גם לחיצה על Enter בשדה טקסט עושה את זה.
action ו-method: לאן ואיך הנתונים הולכים
| מאפיין | ערכים | ברירת מחדל |
|---|---|---|
action | כל URL | ה-URL של העמוד הנוכחי |
method | get, post, dialog | get |
enctype | application/x-www-form-urlencoded, multipart/form-data, text/plain | application/x-www-form-urlencoded |
עם method="get", השדות הופכים למחרוזת השאילתה של הכתובת: טופס חיפוש עם name="q" הולך אל /search?q=blue+shoes. זה נכון לחיפושים ולמסננים, כי אפשר לשמור את התוצאה בסימניות ולשתף אותה. עם method="post", השדות נשלחים בגוף הבקשה ולא מופיעים בשורת הכתובת או בהיסטוריה. השתמשו ב-POST לכל דבר שמתחבר, יוצר, משנה או מוחק משהו, ולסיסמאות.
טופס עם העלאת קובץ (<input type="file">) צריך method="post" ו-enctype="multipart/form-data", אחרת נשלח רק שם הקובץ. method="dialog" מיועד לטופס בתוך <dialog>: השליחה סוגרת את הדיאלוג במקום לשלוח בקשה.
מה נשלח
רק שדות עם name נשלחים, ורק כשהם לא disabled. לחצו על Submit והשוו את השדות למה שהטופס שולח:
הטופס שולח city, zip, source ו-action. השדה בלי שם, השדה המושבת וה-checkbox הלא מסומן נשארים בחוץ. שדות מוסתרים נשלחים אבל אף פעם לא מוצגים, וכפתור השליחה שולח את ה-name וה-value שלו כי זה הכפתור שבו השתמשו.
קיבוץ שדות עם fieldset ו-legend
<fieldset> מצייר תיבה סביב שדות קשורים, ו-<legend> הוא הכיתוב שלה. קוראי מסך מכריזים את ה-legend כשהמיקוד נכנס לקבוצה, וזה מה שהופך קבוצת כפתורי רדיו כמו אלה שלמטה למובנת: "Delivery, Standard, radio button".
disabled על fieldset משבית בבת אחת כל שדה שבתוכו, ואף אחד מהם לא נשלח. הסירו אותו ושדות המתנה יהפכו לשמישים.
אימות מובנה: required, pattern והחברים שלהם
דפדפנים בודקים את המאפיינים האלה לפני השליחה ומציגים הודעה על השדה הראשון שנכשל:
| מאפיין | בודק |
|---|---|
required | השדה לא ריק (checkbox מסומן) |
type="email", type="url" | הערך נראה כמו כתובת אימייל או URL |
minlength, maxlength | אורך הטקסט |
min, max, step | טווח מספרים ותאריכים |
pattern | הערך כולו תואם לביטוי רגולרי |
:invalid ו-:valid מעצבים שדות לפי המצב שלהם. :user-invalid בדרך כלל עדיף: הוא חל רק אחרי שהקורא שינה את השדה ועבר הלאה, או ניסה לשלוח, כך שטופס ריק לא נפתח כשהוא מכוסה באדום.
שלושה דברים ב-pattern מכשילים אנשים. הוא חייב להתאים לערך כולו (אין צורך ב-^ או $). הוא רץ רק כשהשדה לא ריק, אז שלבו אותו עם required. והודעת השגיאה של הדפדפן כללית, אז תארו את הפורמט בטקסט גלוי ליד השדה. Chrome ו-Firefox מוסיפים את טקסט ה-title להודעה שלהם, אבל קל לפספס אותו.
כדי לכבות את הבדיקות, למשל כשאתם בודקים את האימות של השרת, הוסיפו novalidate ל-<form>. כפתור שליחה יחיד יכול לדלג עליהן עם formnovalidate.
אימות בדפדפן נועד לנוחות הקורא. כל אחד יכול לערוך את העמוד או לשלוח בקשה בלעדיו, אז השרת חייב לבדוק כל ערך שוב.
הודעות מותאמות עם setCustomValidity
כשאי אפשר לכתוב כלל כמאפיין, כמו "שתי הסיסמאות חייבות להיות זהות", הגדירו את ההודעה מ-JavaScript. שדה עם הודעה מותאמת לא ריקה הוא לא תקין; מחרוזת ריקה הופכת אותו לתקין שוב:
לשדה החזרה אין name, כך שרק עותק אחד של הסיסמה נשלח.
טיפול בשליחה ב-JavaScript
כדי לשלוח את הטופס בלי לעזוב את העמוד, האזינו ל-submit, קראו ל-preventDefault(), וקראו את השדות עם FormData. האזנה ל-submit ולא ל-click של כפתור תופסת כל דרך שליחה, כולל Enter, ורצה רק אחרי שהאימות המובנה עבר:
Object.fromEntries(new FormData(form)) הופך את השדות לאובייקט פשוט. לשדות שיכולים להיות להם כמה ערכים (checkboxes שחולקים שם, select מרובה) השתמשו ב-formData.getAll('name') במקום, כי האובייקט שומר רק את הערך האחרון.
טעויות נפוצות
- שדות בלי
name. הם נשארים בשקט מחוץ לנתונים שנשלחים. - placeholders במקום תוויות. הרמז נעלם ברגע שהקורא מקליד. השתמשו ב-
<label>. <button>בליtypeשמשמש למשהו אחר חוץ משליחה. בתוך טופס הוא כפתור שליחה.- טופס בתוך טופס. קינון טפסים אינו תקין; הדפדפן מתעלם מתגית ה-
<form>הפנימית. - האזנה ל-
clickעל כפתור השליחה במקום ל-submitעל הטופס. שליחות עם מקש Enter מתפספסות. - הסתמכות על אימות הדפדפן בצד השרת. אמתו שוב שם.
- GET לסיסמאות. הן מגיעות לכתובת, להיסטוריה וללוגים של השרת.
שאלות נפוצות
איך יוצרים טופס ב-HTML?
עטפו את השדות ב-<form action="/signup" method="post">, תנו לכל שדה name ו-<label>, וסיימו עם <button type="submit">. כשהטופס נשלח, הדפדפן שולח כל זוג name=value לכתובת ה-action.
מה ההבדל בין GET ל-POST בטופס?
method="get" (ברירת המחדל) מכניס את השדות לכתובת, כמו /search?q=shoes, מה שמתאים לחיפושים ולמסננים שכדאי שאפשר יהיה לשמור בסימניות. method="post" שולח אותם בגוף הבקשה, וזה מה שרוצים בהתחברות, בהרשמה ובכל דבר שמשנה נתונים.
למה שדה בטופס שלי לא נשלח?
אין לו מאפיין name, או שהוא disabled. רק שדות עם שם ופעילים נשלחים. גם checkbox או כפתור רדיו לא מסומנים לא נכללים בכלל.
בשביל מה משמשים fieldset ו-legend?
<fieldset> מקבץ שדות קשורים ו-<legend> הוא הכיתוב של הקבוצה. קוראי מסך מכריזים את ה-legend כשהמיקוד נכנס לקבוצה, וזה מה שהופך קבוצה של כפתורי רדיו למובנת, ו-disabled על fieldset משבית כל שדה שבתוכו.
איך מאמתים טופס ב-HTML בלי JavaScript?
השתמשו במאפיינים: required, type="email", minlength, maxlength, min, max ו-pattern. הדפדפן חוסם את השליחה ומציג הודעה לשדה הלא תקין הראשון. תמיד אמתו גם בשרת, כי הבדיקות האלה רצות בדפדפן של הקורא ואפשר לעקוף אותן.
איך מונעים מטופס לטעון מחדש את העמוד?
האזינו לאירוע submit של הטופס וקראו ל-event.preventDefault(), ואז שלחו את הנתונים בעצמכם עם fetch: form.addEventListener('submit', (e) => { e.preventDefault(); fetch(form.action, { method: 'POST', body: new FormData(form) }); }).