Mundarija (32)
- Bu darsda
- 1. Nega bu kerak?
- 2. validity — qaysi qoida buzildi
- 2.1 Har maydonning tekshiruv jurnali
- 2.2 Bayroqlar jadvali
- 2.3 Ism nega true?
- 3. checkValidity(), reportValidity() va invalid hodisasi
- 3.1 Jim va ovozli tekshiruv
- 3.2 invalid ko'tarilmaydi
- 4. setCustomValidity — o'z xabaringiz
- 4.1 Qanday ishlaydi
- 4.2 O'zbekcha xabarlar
- 4.3 O'z qoidangiz: faqat probellar
- 5. novalidate va xatolar xulosasi
- 5.1 Pufak yetmaganda
- 5.2 Qaysi yo'lni tanlash
- 6. Hujumchi nigohi
- 7. Ko'p uchraydigan xatolar
- 7.1 setCustomValidity("") unutildi
- 7.2 Xabarni submit ichida qo'yish
- 7.3 invalid ni oddiy tinglovchi bilan ushlash
- 7.4 Har input da reportValidity()
- 7.5 Radio guruhida xabar qolib ketdi
- 7.6 ValidityState {} — "bo'sh obyekt"
- 8. Mashqlar
- 1-mashq (oson): Qaysi bayroq?
- 2-mashq (o'rta): Email uchun o'zbekcha xabar
- 3-mashq (qiyin): Telefon yoki email
- 4-mashq: Portfolio qadami — aloqa formasi o'zbekcha gapiradi
- 9. Real ishda
- Xulosa
- Manbalar
Constraint Validation API: forma tekshiruvini JavaScript'dan boshqarish
Qisqacha: Brauzer
required,pattern,min/maxbo'yicha tekshirgan natijani JavaScript'ga ochiq beradi. Har maydonningvalidityobyekti qaysi qoida buzilganini aytadi:valueMissing,patternMismatchva boshqalar. MetodlardancheckValidity()jim tekshiradi,reportValidity()esa xabar pufagini ko'rsatadi. O'z matningiz uchun —setCustomValidity("matn"): u maydonni xato qiladi va pufakka shu matnni (masalan, o'zbekcha xabarni) qo'yadi, bo'sh satr""esa xatoni olib tashlaydi.
Bu darsda
validityorqali maydonda aynan qaysi qoida buzilganini aniqlaysiz.checkValidity()vareportValidity()farqini bilasiz vainvalidhodisasini tinglaysiz.setCustomValiditybilan brauzer xabarlarini o'zbekchaga almashtirasiz va o'z qoidangizni qo'shasiz.novalidatebilan pufaklarni o'chirib, barcha xatolarni bir joyda — xatolar xulosasida ko'rsatasiz.- Portfolio'dagi aloqa formasi o'zbekcha xabarlar bilan gapiradi.
Oldin bilishingiz kerak: FormData, Brauzer validatsiyasi, input va change: jonli tekshirish, Hodisa tarqalishi: capture va bubble.
1. Nega bu kerak?
Brauzer validatsiyasi darsida bitta muammo ochiq qolgan edi. «Bahor» sayti o'zbekcha, Ali esa formani bo'sh yuborganda pufakda "Please fill out this field." yoki "Заполните это поле." ni ko'radi. Brauzer xabarlari sahifa tilida emas, brauzerning o'z tilida chiqadi. O'shanda "matnni o'zgartirishning yagona yo'li — JavaScript" degan edik.
Ikkinchi muammo — ikki dars oldin, input va change darsida, ism uzunligini va kishi sonini JavaScript'da qaytadan tekshirdik: qiymat.trim().length < 2, odam > 20. Lekin bu qoidalar HTML'da allaqachon yozilgan edi — minlength="2", max="20". Endi har qoida ikki joyda yashaydi. Biri o'zgarsa, ikkinchisi unutiladi. Telefon tekshiruvimiz esa umuman chala chiqdi: +998abcdefghi ham o'tib ketardi.
Brauzer bu tekshiruvni allaqachon bajaryapti — va to'g'ri bajaryapti. Bizga faqat uning natijasini o'qish va xabarini almashtirish imkoni kerak. Shu imkon — Constraint Validation API (cheklovlar bo'yicha tekshiruv API'si). Constraint (cheklov) — maydonga qo'yilgan qoida: required, pattern, max va boshqalar.
Hayotdan o'xshatish: choyxonada ovqat sifatini tekshiradigan sanitariya inspektori. U allaqachon tekshirib, jurnalga yozib qo'ygan. Jasur akaga inspektorni qayta ishga olish shart emas — jurnalni o'qish va kamchilikni mehmonga tushunarli tilda aytish kifoya.
2. validity — qaysi qoida buzildi
2.1 Har maydonning tekshiruv jurnali
Har bir forma maydonida validity xususiyati bor — ValidityState (to'g'rilik holati) obyekti. Unda o'nta mantiqiy qiymat (true/false) — har qoida uchun bittadan — va umumiy valid.
Bu o'nta qiymatni bayroq deb ataymiz. Xuddi stadiondagi hakam bayrog'i kabi: ko'tarilgan bo'lsa (true) — qoida buzilgan, tushirilgan bo'lsa (false) — hammasi joyida.
<form id="bron">
<label>Ism <input name="ism" required minlength="2"
value="A"></label>
<label>Telefon <input name="telefon" type="tel" required
pattern="\+998 ?\d{2} ?\d{3} ?\d{2} ?\d{2}"
value="90 000 00 00"></label>
<label>Kishi <input name="odam" type="number" required
min="1" max="20" value="25"></label>
<label>Vaqt <input name="vaqt" type="time" required
min="10:00" max="22:00" value="23:00"></label>
<label>Email <input name="email" type="email" value="ali"></label>
</form>
<script>
const bayroqlar = [
"valueMissing", "typeMismatch", "patternMismatch",
"tooLong", "tooShort", "rangeUnderflow", "rangeOverflow",
"stepMismatch", "badInput", "customError",
];
const forma = document.querySelector("#bron");
console.log(forma.elements.ism.validity);
for (const maydon of forma.elements) {
const buzilgan = [];
for (const bayroq of bayroqlar) {
if (maydon.validity[bayroq]) {
buzilgan.push(bayroq);
}
}
console.log(maydon.name, maydon.validity.valid, buzilgan);
}
</script>Konsolda:
ValidityState {}
ism true (0) []
telefon false (1) ['patternMismatch']
odam false (1) ['rangeOverflow']
vaqt false (1) ['rangeOverflow']
email false (1) ['typeMismatch']Birinchi qatorga hayron bo'lmang. FormData darsidagi FormData {} ni eslang: u ham bo'sh ko'rinardi, lekin ichi to'la edi. ValidityState {} ham xuddi shunday — uning qiymatlari oddiy xususiyat emas, Chrome konsoli ularni ko'rsatmaydi. Shuning uchun har bayroqni nomma-nom so'radik — maydon.validity[bayroq], kvadrat qavs bilan, chunki nom o'zgaruvchida.
Qolgan qatorlar: har maydonda aynan qaysi qoida buzilgani. Brauzer "xato" deb umumiy aytmaydi — sababini ham aytadi. Endi biz ham mehmonga sababini ayta olamiz.
2.2 Bayroqlar jadvali
| Bayroq | Qachon true |
Qaysi atribut |
|---|---|---|
valueMissing |
Majburiy maydon bo'sh | required |
typeMismatch |
Ko'rinish turga mos emas | type="email", url |
patternMismatch |
Shablonga mos emas | pattern |
tooShort / tooLong |
Juda qisqa / uzun | minlength / maxlength |
rangeUnderflow |
Chegaradan kichik | min |
rangeOverflow |
Chegaradan katta | max |
stepMismatch |
Qadamga tushmaydi (2.5 kishi) | step |
badInput |
Brauzer qiymatni tushunmadi (2e) |
number, sana |
customError |
Kod xato qo'ygan | setCustomValidity |
valid |
Hammasi false — maydon to'g'ri |
— |
2.3 Ism nega true?
Diqqat qiling: ism "A", minlength="2" — lekin ism true, tooShort yo'q! Bu xato emas. Brauzer validatsiyasi darsida aytilgan nozik qoida: minlength va maxlength faqat mehmon maydonga o'zi yozganda tekshiriladi. HTML'dagi value="A" ham, JavaScript yozgan maydon.value = "A" ham bu qoidani ishga tushirmaydi. Mehmon tegmagan qiymat uchun brauzer uni ayblamaydi.
Mehmon o'zi yozsa, qoida darhol ishlaydi. Buni «O'zbekcha xabarlar» bo'limidagi formada ko'rasiz: ism maydoniga bitta harf yozib yuborishga urinsangiz, tooShort xabari chiqadi.
Tekshirib ko'ring:
<input type="number" name="odam" min="1" max="20" step="1">maydoniga mehmon0,2.5,21va bo'sh qiymat yozdi (requiredyo'q). Har biri uchun qaysi bayroqtrue?
Javob
0 — rangeUnderflow. 2.5 — stepMismatch (qadam 1, ya'ni faqat butun son). 21 — rangeOverflow. Bo'sh — hech biri: required bo'lmasa, bo'sh maydon to'g'ri hisoblanadi, valid — true.
3. checkValidity(), reportValidity() va invalid hodisasi
3.1 Jim va ovozli tekshiruv
validity — tayyor natija. Formani yoki maydonni "hozir tekshir" deb so'rash uchun ikki metod bor:
<form id="bron">
<label>Ism <input name="ism" required></label>
<label>Kishi <input name="odam" type="number"
required min="1" max="20"></label>
</form>
<button type="button" id="jim">checkValidity()</button>
<button type="button" id="ovozli">reportValidity()</button>
<script>
const forma = document.querySelector("#bron");
forma.addEventListener("invalid", (event) => {
console.log("invalid:", event.target.name);
}, true);
document.querySelector("#jim").addEventListener("click", () => {
console.log("checkValidity:", forma.checkValidity());
});
document.querySelector("#ovozli").addEventListener("click", () => {
console.log("reportValidity:", forma.reportValidity());
console.log("fokus:", document.activeElement.name);
});
</script>«checkValidity()» ni bosing — konsolda uch qator chiqadi, ekranda esa hech narsa o'zgarmaydi:
invalid: ism
invalid: odam
checkValidity: falseEndi «reportValidity()» ni bosing. Konsolda yana ikkita invalid, keyin reportValidity: false va fokus: ism. Ekranda esa ism maydoni yonida brauzer pufagi paydo bo'ldi va fokus o'sha maydonga o'tdi.
checkValidity() |
reportValidity() |
|
|---|---|---|
| Natija | true / false |
true / false |
invalid hodisasi |
Har xato maydonda | Har xato maydonda |
| Pufak va fokus | Yo'q — jim | Birinchi xato maydonda |
Ikkalasi ham formada ham, alohida maydonda ham ishlaydi: forma.checkValidity() — butun forma, ism.checkValidity() — faqat ism. Formaning o'zida validity yo'q (forma.validity — undefined), lekin bu ikki metod bor.
Qachon qaysi biri? checkValidity() — kod uchun savol: "yuborsam bo'ladimi?", "keyingi qadamga o'tkazaymi?". reportValidity() — mehmonga ko'rsatish kerak bo'lganda: masalan, ko'p qadamli formada "Keyingi" tugmasi bosilganda joriy qadamni tekshirish.
3.2 invalid ko'tarilmaydi
Kodga qayting: invalid tinglovchisining uchinchi argumenti — true. Hodisa tarqalishi darsidagi capture bosqichi. Nega kerak?
invalid — kam uchraydigan hodisalardan biri: u ko'tarilmaydi (bubble qilmaydi). Formaga oddiy tinglovchi qo'ysangiz, maydondagi invalid unga yetib kelmaydi. Ikki yo'l bor: har maydonga alohida tinglovchi qo'yish yoki formada capture bosqichida ushlash. Ikkinchisi — bitta tinglovchi, delegatsiya kabi. Uchinchi argumentni olib tashlab sinab ko'ring: konsolda faqat checkValidity: false qoladi.
invalid hodisasi faqat ikki metod chaqirilganda emas, mehmon formani yuborishga uringanda ham keladi — brauzer har xato maydon uchun uni chiqaradi va shundan keyin birinchisiga pufak ko'rsatadi. Bu bizga xabarni pufak chiqishidan oldin almashtirish imkonini beradi.
Tekshirib ko'ring: Ko'p qadamli bron formasida "Keyingi" tugmasi bor. Mehmon xato qilgan bo'lsa, unga pufak ko'rinishi va fokus xato maydonga o'tishi kerak. Qaysi metodni chaqirasiz —
checkValidity()yokireportValidity()?
Javob
reportValidity(). U ham true/false qaytaradi, lekin bundan tashqari birinchi xato maydonda pufak ko'rsatadi va fokusni o'sha yerga o'tkazadi. checkValidity() esa jim: mehmon nega o'tolmayotganini bilmay qolardi.
4. setCustomValidity — o'z xabaringiz
4.1 Qanday ishlaydi
setCustomValidity(matn) — maydonga "kod topgan xato" ni qo'yadi:
- Bo'sh bo'lmagan matn → maydon xato (
customError: true), pufakda shu matn chiqadi. - Bo'sh satr
""→ kod qo'ygan xato olib tashlanadi.
Serverdan "bu vaqtda stol band" degan javob keldi deylik. Brauzer buni bilmaydi, kod esa biladi:
<label>Vaqt <input id="vaqt" type="time" value="19:00"></label>
<script>
const vaqt = document.querySelector("#vaqt");
console.log(vaqt.validity.valid);
vaqt.setCustomValidity("Soat 19:00 da bo'sh stol yo'q.");
console.log(vaqt.validity.valid, vaqt.validity.customError);
console.log(vaqt.validationMessage);
vaqt.value = "20:00";
console.log(vaqt.validity.valid);
vaqt.setCustomValidity("");
console.log(vaqt.validity.valid);
</script>Konsolda:
true
false true
Soat 19:00 da bo'sh stol yo'q.
false
trueTo'rtinchi qator — darsning eng muhim joyi. Qiymat 20:00 ga o'zgardi, lekin maydon hali ham xato. Kod qo'ygan xato o'zi yo'qolmaydi — uni faqat kod olib tashlaydi (setCustomValidity("")). Bu qoidani unutish — eng ko'p uchraydigan xato: mehmon hammasini tuzatdi, forma esa yuborilmaydi va pufakda eski xabar turaveradi.
validationMessage — pufakda ko'rinadigan matn. Kod xato qo'ymagan bo'lsa, unda brauzerning o'z xabari turadi — brauzer tilida. Natijadagi «Tahrirlab ko'rish» bilan setCustomValidity qatorlarini olib tashlab, required qo'shing va value ni bo'shating: konsolda brauzeringiz tilidagi "maydonni to'ldiring" xabari chiqadi. Biz uni bu yerga yozmadik — har kompyuterda boshqacha.
4.2 O'zbekcha xabarlar
Endi asosiy vazifa. Rejamiz:
- Bayroqqa qarab o'zbekcha matn tanlaydigan funksiya —
xabarniTop. - Maydon xabarini yangilaydigan funksiya —
xabarniYangila: avval eski xabarni tozalaydi (""), keyin brauzer nima deyishini tekshiradi va kerak bo'lsa o'zbekcha matnni qo'yadi. - Uni ikki paytda chaqirish:
invalidda (yuborishga urinish — pufakdan oldin) vainputda (mehmon tuzatyapti — eski xabar qolib ketmasin).
Ikki yo'l bitta funksiyaga kelib tutashadi:
flowchart TD
Y["Mehmon yozdi: input"] --> T["Eski xabarni tozalash"]
B["Yuborish bosildi: invalid"] --> T
T --> V{"Brauzer qoidalari bajarildimi?"}
V -->|"Ha"| OK["Xabar yo'q, maydon to'g'ri"]
V -->|"Yo'q"| X["O'zbekcha xabar qo'yiladi"]
X --> P["Pufak va :user-invalid shu xabar bilan"]Nimaga qarang: qaysi yo'ldan kelmasin, avval tozalash. Shu tufayli eski xabar hech qachon qolib ketmaydi.
<style>
form { display: grid; gap: 4px; max-width: 320px; }
input { padding: 6px; border: 2px solid #5b6660; }
input:user-invalid { border-color: #b3261e; }
input:user-valid { border-color: #2e7d32; }
button { margin-top: 8px; padding: 8px; }
</style>
<form action="https://example.com/bron" method="post">
<label for="ism">Ismingiz (2–50 belgi)</label>
<input id="ism" name="ism" required minlength="2" maxlength="50">
<label for="telefon">Telefon (+998 90 000 00 00)</label>
<input id="telefon" name="telefon" type="tel" required
pattern="\+998 ?\d{2} ?\d{3} ?\d{2} ?\d{2}"
title="+998 va 9 ta raqam: +998 90 000 00 00">
<label for="odam">Necha kishi (1–20)</label>
<input id="odam" name="odam" type="number"
required min="1" max="20">
<label for="vaqt">Soat nechada (10:00–22:00)</label>
<input id="vaqt" name="vaqt" type="time" required
min="10:00" max="22:00">
<button type="submit">Bron qilish</button>
</form>
<script>
const forma = document.querySelector("form");
function xabarniTop(maydon) {
const v = maydon.validity;
if (v.valueMissing) {
return "Bu maydonni to'ldiring.";
}
if (v.tooShort) {
return `Kamida ${maydon.minLength} ta belgi yozing ` +
`(hozir ${maydon.value.length} ta).`;
}
if (v.patternMismatch) {
return `Format: ${maydon.title}.`;
}
if (v.rangeUnderflow) {
return `Eng kamida ${maydon.min} bo'lsin.`;
}
if (v.rangeOverflow) {
return `Ko'pi bilan ${maydon.max} bo'lsin.`;
}
if (v.stepMismatch || v.badInput) {
return "Butun son kiriting.";
}
return "Qiymatni tekshiring.";
}
function xabarniYangila(maydon) {
maydon.setCustomValidity("");
if (!maydon.validity.valid) {
maydon.setCustomValidity(xabarniTop(maydon));
}
}
forma.addEventListener("invalid", (event) => {
const maydon = event.target;
xabarniYangila(maydon);
console.log(maydon.name, "—", maydon.validationMessage);
}, true);
forma.addEventListener("input", (event) => {
xabarniYangila(event.target);
});
forma.addEventListener("submit", (event) => {
event.preventDefault();
console.log("Forma to'g'ri, yuborish mumkin");
});
</script>Formani bo'sh qoldirib «Bron qilish» ni bosing. Ism yonidagi pufakda endi "Bu maydonni to'ldiring." turadi — brauzer qaysi tilda bo'lishidan qat'i nazar. Konsolda esa barcha to'rtta xato maydonning o'zbekcha xabari chiqadi (pufak faqat birinchisini ko'rsatadi):
ism — Bu maydonni to'ldiring.
telefon — Bu maydonni to'ldiring.
odam — Bu maydonni to'ldiring.
vaqt — Bu maydonni to'ldiring.Endi qiymatlar bilan sinang:
- ismga bitta harf → "Kamida 2 ta belgi yozing (hozir 1 ta).";
- telefonga
90 000 00 00→ "Format: +998 va 9 ta raqam: +998 90 000 00 00."; - kishi soniga
25→ "Ko'pi bilan 20 bo'lsin."; - vaqtga
23:00→ "Ko'pi bilan 22:00 bo'lsin.".
Hammasini to'g'ri to'ldirsangiz, konsolda "Forma to'g'ri, yuborish mumkin" chiqadi.
Kodning uch muhim joyi:
- Xabar matnlari HTML'dan olinadi.
maydon.minLength,maydon.max,maydon.title— HTML atributlarining JavaScript xususiyatlari. Qoida bitta joyda — HTML'da — qoldi.max="20"ni30ga o'zgartirsangiz, xabar ham o'zi "Ko'pi bilan 30" bo'ladi. xabarniYangilaavval tozalaydi.setCustomValidity("")dan keyinvalidityfaqat brauzerning o'z qoidalarini ko'rsatadi. Tozalamasak, eski xabarcustomErrorbo'lib qolib ketardi va maydon hech qachon to'g'ri bo'lmasdi.- Brauzer qoidalari o'chirilmadi.
required,pattern,min/maxishlayveradi, pufak ham,:user-invalidham. Biz faqat matnni almashtirdik.
Ramkalarga qarang: maydondan chiqqaningizda u qizil yoki yashil bo'ldi. Bu — CSS'dagi :user-invalid va :user-valid (Holat pseudo-klasslari). setCustomValidity qo'ygan xato ham ular uchun xato: JavaScript va CSS bitta manbaga — validity ga — qaraydi.
Maslahat: Chrome ekran o'quvchiga ham shu manbadan "noto'g'ri" holatini beradi. Accessibility daraxtida (DevTools → Elements → Accessibility) tekshirdik: mehmon tegib chiqqan xato maydonda
invalid: truepaydo bo'ladi, tegilmaganda —false. Ya'ni:user-invalidqoidasi Malika uchun ham ishlaydi,aria-invalidni qo'lda qo'yish shart emas.
4.3 O'z qoidangiz: faqat probellar
Brauzer validatsiyasi darsidan eslang: uchta probeldan iborat ism required dan o'tadi. Brauzerda bunday qoida yo'q — demak, uni biz qo'shamiz. xabarniYangila ga bitta shart:
function xabarniYangila(maydon) {
maydon.setCustomValidity("");
const faqatProbel =
maydon.value !== "" && maydon.value.trim() === "";
if (faqatProbel) {
maydon.setCustomValidity("Faqat probel yetmaydi, matn yozing.");
return;
}
if (!maydon.validity.valid) {
maydon.setCustomValidity(xabarniTop(maydon));
}
}Shu yo'l bilan istalgan qoidani qo'shish mumkin: "sana o'tib ketmagan bo'lsin", "ikki parol bir xil bo'lsin". Kod tekshiradi va setCustomValidity bilan brauzer tizimiga "ulab" qo'yadi. Shundan keyin u brauzer qoidasi kabi ishlaydi: forma yuborilmaydi, pufak chiqadi, :user-invalid qizartiradi.
Tekshirib ko'ring: Nega
xabarniYangilani faqatinvalidda chaqirish yetarli emas?inputtinglovchisini olib tashlasak nima bo'ladi?
Javob
Chrome'da sinab ko'rdik. Ali bo'sh formani yuboradi — invalid keladi va ismga "Bu maydonni to'ldiring." qo'yiladi. Ali "Ali" deb yozadi, lekin kod qo'ygan xato o'zi yo'qolmaydi: maydon hali ham xato va ramkasi qizil. Ali «Bron qilish» ni bosadi — forma yana yuborilmaydi. Shu urinishda invalid xabarni tozalaydi, shuning uchun faqat ikkinchi bosishda forma ketadi.
Mehmon uchun bu — to'g'ri yozilgan maydon ustida qizil ramka va "ishlamaydigan" tugma. input tinglovchisi xabarni yozish paytida yangilab boradi va bu chalkashlikni butunlay yo'q qiladi.
5. novalidate va xatolar xulosasi
5.1 Pufak yetmaganda
Pufak qulay, lekin cheklangan: bir vaqtda faqat bitta xato ko'rinadi, uni bezab bo'lmaydi, bir necha soniyada yo'qoladi. Uzun formada mehmon xatolarni birma-bir "ovlaydi". Qulay va accessible forma darsida yaxshiroq yo'lni ko'rgan edik — forma tepasida xatolar xulosasi: barcha xatolar ro'yxati, har biri maydonga havola. O'shanda "fokusni xulosaga ko'chirish uchun JavaScript kerak" degan edik.
Buning uchun formaga novalidate qo'yamiz (Brauzer validatsiyasi): brauzer pufak ko'rsatmaydi va formani to'xtatmaydi — submit hodisasi doim keladi. Qoidalar esa joyida: checkValidity() va validity ishlayveradi. Tekshirish va ko'rsatish endi to'liq bizning qo'limizda.
<style>
form { display: grid; gap: 4px; max-width: 320px; }
input { padding: 6px; border: 2px solid #5b6660; }
input:user-invalid { border-color: #b3261e; }
#xatolar { border: 2px solid #b3261e; padding: 0 12px; }
#xatolar a { color: #b3261e; }
</style>
<div id="xatolar" tabindex="-1" hidden>
<h2></h2>
<ul></ul>
</div>
<form action="https://example.com/bron" method="post" novalidate>
<label for="ism">Ismingiz (2–50 belgi)</label>
<input id="ism" name="ism" required minlength="2" maxlength="50">
<label for="odam">Necha kishi (1–20)</label>
<input id="odam" name="odam" type="number"
required min="1" max="20">
<button type="submit">Bron qilish</button>
</form>
<script>
const forma = document.querySelector("form");
const xulosa = document.querySelector("#xatolar");
const sarlavha = xulosa.querySelector("h2");
const royxat = xulosa.querySelector("ul");
const xabarlar = {
ism: "Ismingizni yozing: kamida 2 harf.",
odam: "Kishi sonini 1 dan 20 gacha yozing.",
};
forma.addEventListener("submit", (event) => {
event.preventDefault();
royxat.textContent = "";
let soni = 0;
for (const maydon of forma.elements) {
if (!maydon.checkValidity()) {
soni = soni + 1;
const havola = document.createElement("a");
havola.href = `#${maydon.id}`;
havola.textContent = xabarlar[maydon.name];
const qator = document.createElement("li");
qator.append(havola);
royxat.append(qator);
}
}
if (soni === 0) {
xulosa.hidden = true;
console.log("Forma to'g'ri — serverga yuborish mumkin");
return;
}
sarlavha.textContent = `Formada ${soni} ta xato bor`;
xulosa.hidden = false;
xulosa.focus();
});
</script>Formani bo'sh qoldirib «Bron qilish» ni bosing:
- Forma tepasida qizil ramkali blok chiqdi: "Formada 2 ta xato bor" va ikki havola.
- Fokus blokka o'tdi —
xulosa.focus(). Ekran o'quvchi Malika birinchi bo'lib "Formada 2 ta xato bor" ni eshitadi. - "Ismingizni yozing" havolasini bosing — fokus ism maydoniga o'tadi, mehmon darhol yozadi.
- Ikkala maydon ramkasi ham qizardi:
novalidatebo'lsa ham, yuborishga urinishdan keyin:user-invalidishlaydi (Chrome 154 da tekshirdik).
Kodning ikki nozik joyi:
tabindex="-1"—divodatda fokus olmaydi.-1uniTabtartibiga qo'shmaydi, lekinfocus()ga ruxsat beradi (Klaviatura va fokus boshqaruvi).royxat.textContent = ""— har yuborishda eski ro'yxat tozalanadi, aks holda xatolar ikki marta yozilardi.
5.2 Qaysi yo'lni tanlash
Pufak + setCustomValidity |
novalidate + o'z ko'rinishingiz |
|
|---|---|---|
| Kod hajmi | Kam | Ko'proq |
| Bir vaqtda ko'rinadigan xato | Bitta | Hammasi |
| Ko'rinishi | Brauzerniki, bezab bo'lmaydi | O'zingiz bezaysiz |
| Til | Sizning matningiz | Sizning matningiz |
Kichik forma (2–4 maydon) — birinchi yo'l yetarli. Uzun forma, ro'yxatdan o'tish, to'lov — ikkinchisi. Ikkalasida ham qoidalar HTML'da qoladi va JavaScript ularni validity orqali o'qiydi.
Tekshirib ko'ring: Xatolar xulosasi bor formadan
novalidateni olib tashlasak, mehmon bo'sh formani yuborganda xulosa chiqadimi?
Javob
Yo'q. novalidate siz brauzer formani o'zi to'xtatadi va pufak ko'rsatadi — xato formada submit hodisasi umuman kelmaydi. Bizning xulosa chizadigan kodimiz esa aynan submit tinglovchisida turibdi, u ishga tushmaydi.
6. Hujumchi nigohi
Bu darsdagi hamma narsa — mijozdagi tekshiruv. Hujumchi uchun:
setCustomValidityqo'ygan xatoni DevTools konsolida bitta qator bilan olib tashlaydi:document.querySelector("#ism").setCustomValidity("").novalidateli formada esa tekshiruvning o'zi bizningsubmittinglovchimizda. Tinglovchini o'chirish — DevTools'ning Event Listeners yorlig'ida bitta "Remove".curluchun bu formaning umuman ahamiyati yo'q.
Demak, «faqat probellar» kabi o'z qoidangizni qo'shsangiz, uni serverda ham yozing. Eng yaxshi amaliyot — qoidalarni bir marta yozib, ham brauzerda, ham serverda ishlatish. Buni backend qismida, Validatsiya: nima uchun, qayerda va qanday darsida ko'ramiz. Brauzer tekshiruvi mehmonning vaqti uchun, server tekshiruvi — xavfsizlik uchun.
7. Ko'p uchraydigan xatolar
7.1 setCustomValidity("") unutildi
Mehmon xatoni tuzatdi, forma esa yuborilmaydi, pufakda eski matn. Tuzatish: har tekshiruvni setCustomValidity("") bilan boshlang («O'zbekcha xabarlar» bo'limidagi xabarniYangila kabi).
7.2 Xabarni submit ichida qo'yish
// ❌ hech qachon ishlamaydi
forma.addEventListener("submit", () => {
ism.setCustomValidity("Ismni yozing.");
});Forma xato bo'lsa, submit umuman kelmaydi — brauzer uni invalid bosqichida to'xtatadi va o'z xabarini ko'rsatadi. To'g'ri forma esa endi xato bo'lib qoladi va keyingi urinishda to'xtaydi. Tuzatish: xabarni invalid va input da qo'ying.
7.3 invalid ni oddiy tinglovchi bilan ushlash
forma.addEventListener("invalid", ...) — uchinchi argumentsiz — hech narsa ushlamaydi: invalid ko'tarilmaydi. Tuzatish: capture — addEventListener("invalid", fn, true) — yoki har maydonga alohida tinglovchi.
7.4 Har input da reportValidity()
Har harfda pufak chiqadi va fokus xato maydonga sakraydi — mehmon boshqa maydonga o'ta olmay qoladi. Tuzatish: input da faqat setCustomValidity (jim), ko'rsatishni brauzer yoki submit ga qoldiring.
7.5 Radio guruhida xabar qolib ketdi
Radio guruhida har radio alohida maydon, required esa butun guruhga tegishli. invalid har radio uchun keladi va xabar har biriga qo'yiladi. Mehmon ikkinchi radioni bosganda faqat o'shaning xabarini tozalasangiz, birinchisida customError qoladi. Chrome'da ikki holatni sinadik. invalid da xabarni shunchaki qo'yadigan kodda forma hech qachon ketmaydi. «O'zbekcha xabarlar» dagi xabarniYangila bilan esa birinchi bosish behuda ketadi, forma faqat ikkinchisida yuboriladi. Tuzatish: radio o'zgarganda butun guruhni yangilang — for (const r of forma.elements[maydon.name]) («Portfolio qadami» da shunday qilamiz).
7.6 ValidityState {} — "bo'sh obyekt"
console.log(maydon.validity) hech narsa ko'rsatmaydi. Tuzatish: kerakli bayroqni so'rang: maydon.validity.valueMissing yoki «Har maydonning tekshiruv jurnali» dagi kabi ro'yxat bilan.
8. Mashqlar
1-mashq (oson): Qaysi bayroq?
Bo'sh joyni bayroq nomi bilan to'ldiring:
<input type="email" value="malika">→<input required>, bo'sh →<input type="number" max="20">, mehmon30yozdi →<input pattern="\d{4}">, mehmon12a4yozdi →- Kod
setCustomValidity("Band")chaqirdi →
Yechim
typeMismatch—@yo'q.valueMissing.rangeOverflow—maxdan katta.patternMismatch— shablonda 4 ta raqam,araqam emas.customError— kod qo'ygan xato.
2-mashq (o'rta): Email uchun o'zbekcha xabar
«O'zbekcha xabarlar» bo'limidagi formaga ixtiyoriy email maydonini qo'shing (type="email", required siz). xabarniTop ga typeMismatch uchun shart yozing: "Email to'liq bo'lsin: ali@example.com". Bo'sh email xato bermasligini tekshiring.
Yechim
HTML'ga, vaqt maydonidan keyin:
<label for="email">Email (ixtiyoriy)</label>
<input id="email" name="email" type="email">xabarniTop ichiga, valueMissing shartidan keyin:
if (v.typeMismatch) {
return "Email to'liq bo'lsin: ali@example.com";
}ali yozib yuborishga urining — pufakda o'zbekcha matn. Maydonni bo'shatsangiz — xato yo'q: required bo'lmagani uchun bo'sh email to'g'ri. xabarniYangila o'zgarmadi: u input va invalid da yangi maydonni ham o'zi qamrab oldi.
3-mashq (qiyin): Telefon yoki email
«Bahor» ga qo'ng'iroq qilish yoki xat yozish uchun aloqa kerak: telefon yoki email, kamida bittasi. Ikkala maydon ham required siz (har biri yolg'iz ixtiyoriy). Ikkalasi bo'sh bo'lsa — telefon maydonida "Telefon yoki emaildan kamida bittasini yozing." xabari, forma yuborilmasin. Bittasi to'ldirilishi bilan xato yo'qolsin.
Ishora: bu qoida ikki maydonga tegishli — har ikkalasining input ida tekshiring; xabarni setCustomValidity bilan telefonga qo'ying.
Yechim
<form action="https://example.com/bron" method="post">
<label>Telefon <input name="telefon" type="tel"></label>
<label>Email <input name="email" type="email"></label>
<button type="submit">Yuborish</button>
</form>
<script>
const forma = document.querySelector("form");
const telefon = forma.elements.telefon;
const email = forma.elements.email;
function aloqaniTekshir() {
const ikkalasiBosh =
telefon.value.trim() === "" && email.value.trim() === "";
telefon.setCustomValidity(ikkalasiBosh
? "Telefon yoki emaildan kamida bittasini yozing."
: "");
}
aloqaniTekshir();
telefon.addEventListener("input", aloqaniTekshir);
email.addEventListener("input", aloqaniTekshir);
forma.addEventListener("submit", (event) => {
event.preventDefault();
console.log("Aloqa bor:", telefon.value || email.value);
});
</script>Bo'sh holda «Yuborish» ni bosing — pufak telefon maydonida, o'zbekcha matn bilan. Emailga ali@example.com yozing va yana bosing — konsolda Aloqa bor: ali@example.com. aloqaniTekshir() sahifa ochilganda bir marta chaqiriladi: aks holda mehmon hech narsa yozmasdan bossa, forma o'tib ketardi. Xabarni "ikki maydondan biri" ga emas, aniq bitta maydonga qo'ydik — pufak va fokus o'sha yerga boradi.
4-mashq: Portfolio qadami — aloqa formasi o'zbekcha gapiradi
Portfolio aloqa formasida required maydonlar bor: ism, email, mavzu (radio) va xabar. Ularning xato xabarlari hozircha brauzer tilida. UI/UX asoslari darsidagi CSS esa :user-invalid maydonni va uning -yordam matnini qizartiradi.
asosiy.jsdagialoqaFormasiniUlaichida har maydon uchun o'zbekcha xabar yozing:xabarlarobyekti, kalit —name.- «Faqat probellar» qoidasini qo'shing (ism va xabar uchun).
- Xabarlarni
invalid(capture) vainputda yangilang. Radio guruhini butunligicha yangilashni unutmang. - Tekshiring: bo'sh formani yuborish → o'zbekcha pufak; xato maydon qizil (CSS o'zgarmadi); tuzatilgach — yuboriladi.
- Commit:
Aloqa: o'zbekcha xato xabarlari.
Yechim
aloqaFormasiniUla ichiga (submit tinglovchisidan oldin):
const xabarlar = {
ism: "Ismingizni yozing.",
email: "Email'ni to'liq yozing: ali@example.com",
mavzu: "Mavzuni tanlang: ish taklifi yoki savol.",
xabar: "Xabar matnini yozing.",
};
function xabarniYangila(maydon) {
maydon.setCustomValidity("");
const faqatProbel =
maydon.value !== "" && maydon.value.trim() === "";
if (faqatProbel) {
maydon.setCustomValidity("Faqat probel yetmaydi, matn yozing.");
} else if (!maydon.validity.valid) {
maydon.setCustomValidity(xabarlar[maydon.name] ?? "Tekshiring.");
}
}
function guruhniYangila(maydon) {
if (maydon.type === "radio") {
for (const radio of forma.elements[maydon.name]) {
xabarniYangila(radio);
}
} else {
xabarniYangila(maydon);
}
}
forma.addEventListener("invalid", (event) => {
guruhniYangila(event.target);
}, true);
forma.addEventListener("input", (event) => {
guruhniYangila(event.target);
});Natijani shu parchada tekshiring:
<style>
:is(input, textarea):user-invalid {
outline: 2px solid #b3261e;
}
</style>
<form action="https://example.com/aloqa" method="post">
<p><label for="ism">Ismingiz</label>
<input id="ism" name="ism" required maxlength="60"></p>
<fieldset>
<legend>Qaysi mavzuda?</legend>
<p><input id="mavzu-ish" name="mavzu" type="radio"
value="ish" required>
<label for="mavzu-ish">Ish taklifi</label></p>
<p><input id="mavzu-savol" name="mavzu" type="radio"
value="savol">
<label for="mavzu-savol">Savol</label></p>
</fieldset>
<button type="submit">Yuborish</button>
</form>
<script>
const forma = document.querySelector("form");
const xabarlar = {
ism: "Ismingizni yozing.",
mavzu: "Mavzuni tanlang: ish taklifi yoki savol.",
};
function xabarniYangila(maydon) {
maydon.setCustomValidity("");
const faqatProbel =
maydon.value !== "" && maydon.value.trim() === "";
if (faqatProbel) {
maydon.setCustomValidity(
"Faqat probel yetmaydi, matn yozing.");
} else if (!maydon.validity.valid) {
const matn = xabarlar[maydon.name] ?? "Tekshiring.";
maydon.setCustomValidity(matn);
}
}
function guruhniYangila(maydon) {
if (maydon.type === "radio") {
for (const radio of forma.elements[maydon.name]) {
xabarniYangila(radio);
}
} else {
xabarniYangila(maydon);
}
}
forma.addEventListener("invalid", (event) => {
const maydon = event.target;
guruhniYangila(maydon);
console.log(maydon.id, "—", maydon.validationMessage);
}, true);
forma.addEventListener("input", (event) => {
guruhniYangila(event.target);
});
forma.addEventListener("submit", (event) => {
event.preventDefault();
console.log("Yuborildi:", forma.elements.mavzu.value);
});
</script>Bo'sh formani yuboring — konsolda uchta o'zbekcha xabar (ism, mavzu-ish, mavzu-savol), pufak esa ism yonida. Ismga uchta probel yozing — pufak "Faqat probel yetmaydi". Ismni yozing, "Savol" ni tanlang va yuboring — Yuborildi: savol. guruhniYangila siz "Savol" ni tanlaganda "Ish taklifi" radiosida eski xabar qolardi va birinchi «Yuborish» behuda ketardi (Chrome'da sinadik) («Radio guruhida xabar qolib ketdi» xatosi).
9. Real ishda
- O'zbek va rus tilidagi saytlar brauzer xabarlarining aralash tilini aynan shu API bilan yo'q qiladi. Kichik formalarda —
setCustomValidity, kattalarida —novalidateva o'z ko'rinishi. - Forma kutubxonalari (React Hook Form, Zod — kursda alohida o'rganamiz, hozir bilish shart emas) ko'pincha
novalidatebilan ishlaydi va xatolarni o'zi chizadi. Lekinrequiredvatypeatributlari baribir yoziladi: JavaScript yuklanmasa ham, brauzer tekshiruvi qoladi. - Ko'p qadamli formalar (to'lov, ro'yxatdan o'tish) har qadamda
reportValidity()chaqiradi: "Keyingi" tugmasi joriy qadam to'g'ri bo'lmaguncha o'tkazmaydi. - Intervyuda: "Brauzer xabarini qanday o'zgartirasiz?", "
checkValidityvareportValidityfarqi?", "novalidateqachon kerak?" — bugungi uchta bo'lim.
Xulosa
maydon.validity— qaysi qoida buzilganini aytadi:valueMissing,patternMismatch,rangeOverflowva yana yettita bayroq;valid— umumiy natija.minlength/maxlengthfaqat mehmon yozgan qiymatni tekshiradi — HTML yoki kod yozgani tekshirilmaydi.checkValidity()— jim,reportValidity()— pufak va fokus bilan; ikkalasiinvalidchiqaradi,invalidesa ko'tarilmaydi (capture bilan ushlang).setCustomValidity("matn")— xato va o'z xabaringiz;""— tozalash. Har tekshiruvni tozalashdan boshlang.- Xabarni
invalidvainputda yangilang; radio guruhini butunligicha. novalidate— pufaksiz, hammasini o'zingiz ko'rsatasiz: xatolar xulosasi va unga fokus.
Keyingi dars: Dinamik UI'da qulaylik (a11y) — JavaScript o'zgartirgan sahifani Malika ekran o'quvchida, Bobur esa faqat klaviatura bilan ham to'liq ishlata olsin: aria-live, fokus va aria-expanded.
Manbalar
- MDN: "Constraint validation API", "ValidityState", "HTMLInputElement: setCustomValidity()" — developer.mozilla.org
- MDN: "HTMLFormElement: checkValidity()", "reportValidity()", "HTMLInputElement: invalid event" — developer.mozilla.org
- HTML Standard: "Constraints" (constraint validation API) — html.spec.whatwg.org
- web-features (Baseline):
constraint-validation— keng tarqalgan, 2021-yildan;user-pseudos— 2026-yil maydan keng tarqalgan
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!