15-bo‘lim

Formalar va validatsiya

Forma elementlari bilan ishlash, submit hodisasi, FormData, brauzer validatsiyasi va o'z tekshiruvlaringiz.

🕑 17 daqiqa o‘qish 📄 815 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Qiymatlarni o'qish
  2. submit hodisasi
  3. FormData - hamma maydonni birdan
  4. Brauzer validatsiyasi
  5. validity obyekti
  6. O'z xato xabarlaringiz
  7. To'liq validatsiya naqshi
  8. input va change farqi
  9. Xulosa

Forma - foydalanuvchi bilan ilova o'rtasidagi asosiy ko'prik. Uni to'g'ri ishlatish ma'lumot sifatini belgilaydi.

JavaScript
document.body.innerHTML = `
<form id="ariza">
    <input type="text" name="ism" id="ism" required minlength="3">
    <input type="email" name="email" id="email" required>
    <input type="number" name="yosh" id="yosh" min="18" max="100">
    <input type="checkbox" name="shartlar" id="shartlar">
    <select name="shahar" id="shahar">
        <option value="">Tanlang</option>
        <option value="nam">Namangan</option>
        <option value="tosh">Toshkent</option>
    </select>
    <textarea name="izoh" id="izoh"></textarea>
    <input type="radio" name="jins" value="erkak" id="erkak">
    <input type="radio" name="jins" value="ayol" id="ayol">
    <button type="submit">Yuborish</button>
</form>`;

Qiymatlarni o'qish #

JavaScript
const ism = document.getElementById("ism");
const shartlar = document.getElementById("shartlar");
const shahar = document.getElementById("shahar");

ism.value = "Husanboy";
shartlar.checked = true;
shahar.value = "nam";

console.log("Matn maydoni :", ism.value);
console.log("Katakcha     :", shartlar.checked);
console.log("Tanlangan    :", shahar.value);
console.log("Tanlangan matn:", shahar.selectedOptions[0].textContent);

// Radio - guruhdan tanlanganini topish
document.getElementById("ayol").checked = true;
const jins = document.querySelector("input[name='jins']:checked");
console.log("Radio        :", jins.value);

// Son maydoni - value HAR DOIM satr
const yosh = document.getElementById("yosh");
yosh.value = "25";
console.log("yosh.value turi     :", typeof yosh.value);
console.log("yosh.valueAsNumber  :", typeof yosh.valueAsNumber);
Natija
Matn maydoni : Husanboy
Katakcha     : true
Tanlangan    : nam
Tanlangan matn: Namangan
Radio        : ayol
yosh.value turi     : string
yosh.valueAsNumber  : number
input.value har doim satr

Bu eng ko'p uchraydigan forma xatosi:

JavaScript
const yosh = document.getElementById("yosh").value;    // "25" - satr!

if (yosh > 18) { }              // ishlaydi - satr songa aylanadi
console.log(yosh + 1);          // "251"  (!) - satr ulanadi

type="number" bo'lsa ham .value satr qaytaradi.

Uch yechim:

JavaScript
Number(maydon.value)            // 25
parseInt(maydon.value, 10)      // 25
maydon.valueAsNumber            // 25 - eng toza

valueAsNumber afzal: u type="number" va type="date" uchun maxsus yaratilgan va bo'sh maydonda NaN qaytaradi (Number("") esa 0 beradi - bu xato manbai).

JavaScript
Number("")                      // 0    - xavfli!
document.getElementById("yosh").valueAsNumber   // NaN - to'g'ri

submit hodisasi #

JavaScript
const forma = document.getElementById("ariza");
let yuborildi = false;
let malumot = null;

forma.addEventListener("submit", (hodisa) => {
    hodisa.preventDefault();       // sahifa qayta yuklanmasin

    yuborildi = true;
    malumot = {
        ism: forma.ism.value,
        email: forma.email.value
    };
});

// Maydonlarni to'ldiramiz
forma.ism.value = "Malika";
forma.email.value = "[email protected]";

forma.dispatchEvent(new Event("submit", { bubbles: true, cancelable: true }));

console.log("Yuborildimi?:", yuborildi);
console.log("Ism         :", malumot.ism);
console.log("Email       :", malumot.email);
Natija
Yuborildimi?: true
Ism         : Malika
Email       : [email protected]
Formaga nom orqali murojaat

forma.ism yozuvi ishlaydi - forma o'z maydonlariga name atributi bo'yicha murojaat qilish imkonini beradi:

JavaScript
forma.ism.value          // <input name="ism">
forma.elements.ism       // aniqroq yozuv
forma.elements["email"]  // nomda chiziqcha bo'lsa

forma.elements ishlatish afzalroq - u faqat maydonlarni qaytaradi va formaning o'z xossalari bilan chalkashmaydi.

Masalan <input name="id"> bo'lsa, forma.id maydonni emas, formaning id atributini qaytaradi. forma.elements.id esa har doim maydonni beradi.

Xavfli nomlar: id, action, method, submit, length. Ayniqsa name="submit" - u forma.submit() metodini bosib o'tadi va formani dastur orqali yuborib bo'lmay qoladi.

FormData - hamma maydonni birdan #

JavaScript
const forma = document.getElementById("ariza");

forma.ism.value = "Nodira";
forma.email.value = "[email protected]";
forma.yosh.value = "23";
forma.izoh.value = "Izoh matni";
document.getElementById("shartlar").checked = true;
document.getElementById("shahar").value = "tosh";

const malumot = new FormData(forma);

console.log("ism    :", malumot.get("ism"));
console.log("email  :", malumot.get("email"));
console.log("shahar :", malumot.get("shahar"));
console.log("shartlar:", malumot.get("shartlar"));

// Oddiy obyektga aylantirish
const obyekt = Object.fromEntries(malumot);
console.log("Kalitlar:", Object.keys(obyekt).join(", "));
console.log("Obyekt yosh:", obyekt.yosh);
Natija
ism    : Nodira
email  : [email protected]
shahar : tosh
shartlar: on
Kalitlar: ism, email, yosh, shartlar, shahar, izoh
Obyekt yosh: 23
FormData da belgilanmagan katakcha yo'q

Yuqoridagi natijaga e'tibor bering: shartlar qiymati "on" - bu HTML ning odatiy qiymati.

Lekin katakcha belgilanmagan bo'lsa, u FormData da umuman bo'lmaydi:

JavaScript
document.getElementById("shartlar").checked = false;
new FormData(forma).get("shartlar");     // null

Xuddi shunday jins radio guruhi ham - hech biri tanlanmagan bo'lsa, kalit yo'q. Yuqoridagi kalitlar ro'yxatida jins yo'qligining sababi shu.

Shuning uchun serverda kalit borligini tekshiring:

JavaScript
const roziligi = malumot.has("shartlar");     // true/false

Aniq qiymat kerak bo'lsa, katakchaga value bering:

HTML
<input type="checkbox" name="shartlar" value="ha">

Brauzer validatsiyasi #

JavaScript
const ism = document.getElementById("ism");
const email = document.getElementById("email");

// Bo'sh - required buziladi
ism.value = "";
console.log("Bo'sh ism to'g'rimi?:", ism.checkValidity());
console.log("valueMissing        :", ism.validity.valueMissing);

// Juda qisqa - minlength buziladi
ism.value = "ab";
console.log("Qisqa ism to'g'rimi?:", ism.checkValidity());
console.log("tooShort            :", ism.validity.tooShort);

// To'g'ri
ism.value = "Husanboy";
console.log("To'g'ri ism         :", ism.checkValidity());

// Email formati
email.value = "notogri";
console.log("Noto'g'ri email     :", email.checkValidity());
console.log("typeMismatch        :", email.validity.typeMismatch);

email.value = "[email protected]";
console.log("To'g'ri email       :", email.checkValidity());
Natija
Bo'sh ism to'g'rimi?: false
valueMissing        : true
Qisqa ism to'g'rimi?: true
tooShort            : false
To'g'ri ism         : true
Noto'g'ri email     : false
typeMismatch        : true
To'g'ri email       : true
Validatsiya uch darajada bo'lishi kerak 1. HTML atributlari required, minlength type, min, max, pattern Tez, kodsiz Qulaylik uchun 2. JavaScript Murakkab qoidalar Chiroyli xabarlar Yaxshi tajriba Lekin chetlab o'tiladi 3. Server Yagona ishonchli tekshiruv MAJBURIY Chetlab o'tib bo'lmaydi Brauzerdagi validatsiya - qulaylik, himoya emas Hujumchi so'rovni to'g'ridan-to'g'ri serverga yuboradi
Uchala daraja kerak, lekin faqat server ishonchli
Brauzer validatsiyasi xavfsizlik emas

Foydalanuvchi quyidagilarni bemalol qila oladi:

  • F12 bilan required atributini o'chirish;
  • novalidate atributini qo'shish;
  • curl yoki Postman bilan to'g'ridan-to'g'ri so'rov yuborish;
  • JavaScript ni butunlay o'chirish.

Shuning uchun server tomonida yana tekshiring - istisnosiz.

Brauzer validatsiyasi nima uchun kerak:

  • Foydalanuvchi xatoni darhol ko'radi;
  • Server yuki kamayadi;
  • Tajriba yaxshilanadi.

Lekin u himoya emas, faqat qulaylik.

minlength faqat foydalanuvchi yozganda tekshiriladi

Yuqoridagi natijaga e'tibor bering: ism.value = "ab" qo'yilgan bo'lsa ham tooShort false qaytardi.

Bu xato emas - standart shunday talab qiladi. minlength va maxlength faqat qiymatning "iflos" (dirty) bayrog'i o'rnatilganda, ya'ni uni foydalanuvchi tahrirlagan bo'lsa qo'llanadi. Dastur orqali .value berish bu bayroqni o'rnatmaydi.

required esa har doim ishlaydi - shuning uchun valueMissing to'g'ri chiqdi.

Amaliy xulosa: uzunlikni o'zingiz tekshiring, minlength ga tayanmang:

JavaScript
if (maydon.value.length < 3) {
    maydon.setCustomValidity("Kamida 3 belgi");
}

Bu ayniqsa formani dastur orqali to'ldirganda muhim - masalan qoralamani tiklaganda yoki avtomatik to'ldirishda.

validity obyekti #

JavaScript
const yosh = document.getElementById("yosh");

const holatlar = [
    ["", "bo'sh"],
    ["15", "juda kichik"],
    ["150", "juda katta"],
    ["25", "to'g'ri"]
];

for (const [qiymat, izoh] of holatlar) {
    yosh.value = qiymat;
    const v = yosh.validity;

    const muammolar = [];
    if (v.valueMissing) { muammolar.push("valueMissing"); }
    if (v.rangeUnderflow) { muammolar.push("rangeUnderflow"); }
    if (v.rangeOverflow) { muammolar.push("rangeOverflow"); }

    const holat = v.valid ? "OK" : muammolar.join(", ");
    console.log(`${izoh.padEnd(12)} -> ${holat}`);
}
Natija
bo'sh        -> OK
juda kichik  -> rangeUnderflow
juda katta   -> rangeOverflow
to'g'ri      -> OK
Bo'sh maydon nima uchun "OK"?

yosh maydonida required yo'q - shuning uchun bo'sh qoldirish mumkin. min va max esa faqat qiymat bo'lganda tekshiriladi.

Bu mantiqiy: "ixtiyoriy maydon, lekin to'ldirilsa 18-100 oralig'ida bo'lsin".

required qo'shsangiz, bo'sh qiymat valueMissing beradi.

validity ning to'liq ro'yxati:

XossaQachon true
valueMissingrequired, lekin bo'sh
typeMismatchtype="email" formatiga mos emas
patternMismatchpattern regex ga mos emas
tooShort / tooLongminlength / maxlength
rangeUnderflow / rangeOverflowmin / max
stepMismatchstep ga mos emas
badInputBrauzer qiymatni o'qiy olmadi
customErrorsetCustomValidity chaqirilgan
validHammasi joyida

O'z xato xabarlaringiz #

JavaScript
const parol = document.createElement("input");
parol.type = "password";
parol.required = true;
document.getElementById("ariza").appendChild(parol);

function parolniTekshirish(qiymat) {
    if (qiymat.length < 8) {
        return "Parol kamida 8 belgi bo'lishi kerak";
    }
    if (!/[A-Z]/.test(qiymat)) {
        return "Kamida bitta katta harf kerak";
    }
    if (!/\d/.test(qiymat)) {
        return "Kamida bitta raqam kerak";
    }
    return "";
}

const sinovlar = ["qisqa", "uzunlekin", "Uzunlekin", "Uzunlekin1"];

for (const sinov of sinovlar) {
    parol.value = sinov;
    const xato = parolniTekshirish(sinov);
    parol.setCustomValidity(xato);

    console.log(`${sinov.padEnd(12)} -> ${parol.checkValidity() ? "OK" : parol.validationMessage}`);
}
Natija
qisqa        -> Parol kamida 8 belgi bo'lishi kerak
uzunlekin    -> Kamida bitta katta harf kerak
Uzunlekin    -> Kamida bitta raqam kerak
Uzunlekin1   -> OK
setCustomValidity("") ni chaqirishni unutmang
JavaScript
maydon.setCustomValidity("Xato!");
// keyin foydalanuvchi tuzatdi...
maydon.checkValidity();          // HALI HAM false!

Maxsus xato avtomatik tozalanmaydi. Har tekshiruvda uni qayta o'rnatishingiz kerak:

JavaScript
maydon.setCustomValidity(xatoBormi ? "Xabar" : "");

Bo'sh satr - "xato yo'q" degani.

Yuqoridagi misolda aynan shunday qilingan: parolniTekshirish to'g'ri qiymatda bo'sh satr qaytaradi.

To'liq validatsiya naqshi #

JavaScript
const forma = document.getElementById("ariza");

function xatoKorsatish(maydon, xabar) {
    maydon.classList.toggle("xato", Boolean(xabar));
    let element = maydon.nextElementSibling;

    if (!element || !element.classList.contains("xato-xabar")) {
        element = document.createElement("small");
        element.className = "xato-xabar";
        maydon.after(element);
    }

    element.textContent = xabar;
}

function formaniTekshirish() {
    const xatolar = [];

    for (const maydon of forma.elements) {
        if (!maydon.name) {
            continue;
        }

        if (!maydon.checkValidity()) {
            xatoKorsatish(maydon, maydon.validationMessage);
            xatolar.push(maydon.name);
        } else {
            xatoKorsatish(maydon, "");
        }
    }

    return xatolar;
}

// Bo'sh forma
forma.ism.value = "";
forma.email.value = "";
console.log("Bo'sh formada xatolar:", formaniTekshirish().join(", "));

// To'ldirilgan forma
forma.ism.value = "Aziza";
forma.email.value = "[email protected]";
console.log("To'ldirilgandan keyin:", formaniTekshirish().length, "ta xato");
console.log("Xato klassi qoldimi? :", forma.ism.classList.contains("xato"));
Natija
Bo'sh formada xatolar: ism, email
To'ldirilgandan keyin: 0 ta xato
Xato klassi qoldimi? : false

input va change farqi #

JavaScript
const maydon = document.getElementById("ism");
const hodisalar = [];

maydon.addEventListener("input", () => hodisalar.push("input"));
maydon.addEventListener("change", () => hodisalar.push("change"));

// input - har o'zgarishda
maydon.value = "H";
maydon.dispatchEvent(new Event("input"));
maydon.value = "Hu";
maydon.dispatchEvent(new Event("input"));

// change - fokus yo'qolganda
maydon.dispatchEvent(new Event("change"));

console.log("Hodisalar:", hodisalar.join(" -> "));
Natija
Hodisalar: input -> input -> change
HodisaQachonNima uchun
inputHar belgi kiritilgandaJonli qidiruv, belgi sanash
changeFokus yo'qolgandaYakuniy tekshiruv
Jonli qidiruvda input ni sekinlashtiring
JavaScript
maydon.addEventListener("input", () => {
    qidirish(maydon.value);        // har belgida server so'rovi!
});

"salom" yozgan foydalanuvchi 5 ta so'rov yuboradi.

Debounce naqshi bu muammoni hal qiladi:

JavaScript
let taymer;

maydon.addEventListener("input", () => {
    clearTimeout(taymer);
    taymer = setTimeout(() => qidirish(maydon.value), 300);
});

Endi foydalanuvchi 300 ms to'xtaganda bitta so'rov ketadi.

Har harfda javob kerak bo'lsa (masalan belgi sanash) - debounce shart emas, input to'g'ridan-to'g'ri ishlatiladi.

Amaliy topshiriq
  1. Matn, katakcha va tanlov maydonlaridan qiymat o'qing.
  2. Radio guruhidan tanlanganini :checked bilan toping.
  3. value satr ekanini isbotlab, valueAsNumber bilan tuzating.
  4. submit da preventDefault chaqirib, ma'lumotni yig'ing.
  5. FormData va Object.fromEntries bilan obyekt yasang.
  6. Belgilanmagan katakcha FormData da yo'qligini ko'rsating.
  7. checkValidity va validity xossalarini sinang.
  8. setCustomValidity bilan parol qoidalarini yozing.
  9. Xatoni tozalash uchun bo'sh satr berish kerakligini ayting.
  10. input va change hodisalarini taqqoslang.

Xulosa #

  • input.value har doim satr - valueAsNumber ishlating.
  • Number("") 0 beradi, valueAsNumber esa NaN.
  • submit da preventDefault chaqiring.
  • Maydonlarga forma.elements.nom orqali murojaat qiling.
  • FormData barcha maydonni bir yo'la yig'adi.
  • Belgilanmagan katakcha FormData da umuman bo'lmaydi.
  • checkValidity va validity brauzer tekshiruvini beradi.
  • Brauzer validatsiyasi - qulaylik, xavfsizlik emas.
  • Serverda albatta qayta tekshiring.
  • setCustomValidity("") bilan xatoni tozalashni unutmang.
  • input har belgida, change fokus yo'qolganda ishlaydi.
  • Jonli qidiruvda debounce qo'llang.

Keyingi bo'limda asinxron JavaScript va hodisalar siklini o'rganamiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.