Formularze - Constraint validation API

Walidacja w czystym HTML

Od kilku lat w HTML5 dostępna jest wbudowana walidacja, która swoje działanie opiera o zastosowanie odpowiednich typów pól formularza i atrybutów dla nich.

Jest to bardzo ciekawe pomysł, który pozwala wprowadzać walidację bez pisania kawałka kodu. Dzięki odpowiedniemu stworzeniu kodu formularza tylko zyskujemy. Dostajemy "darmową" walidację, która działa nawet, gdy użytkownik ma wyłączony Javascript. Po drugie dzięki zastosowaniu odpowiednich typów pól (np. type="email" dla pola z emailem, type="number" dla liczb) zyskujemy dodatkowe poprawienie użyteczności naszego formularza, bo np. na urządzeniach mobilnych wyświetlane są odpowiednie klawiatury. Same plusy.

Listę dostępnych typów pól najlepiej zobaczyć na stronie https://developer.mozilla.org/pl/docs/Web/HTML/Element/Input. Warto mieć jednak na uwadze, że nowe rodzaje pól nie w każdej przeglądarce będą się wyświetlać tak samo.

Jeżeli chodzi o atrybuty, to mamy kilka do wykorzystania:

required
określa czy dane pole ma być wypełnione

minlength, maxlength

atrybuty określające minimalna i maksymalną długość wpisywanego tekstu

min, max

określa minimalną i maksymalną liczbę w polach numerycznych lub dla pól range

type

określa typ pola. Niektóre z pól mają swoją własną domyślną walidację. I tak np. pola typu email wymagają wpisania emaila, a pola url wpisania odpowiedniego adresu url

pattern

pozwalają nam podać własny wzór (w formacie regexp) który będzie używany do testu poprawności pola

Spróbujmy to wykorzystać z prostym formularzu kontaktowym:

<form class="form" id="formTest1" method="post">
    <div class="form-row">
        <label for="name" class="form-label">Imię*</label>
        <input type="text" class="form-control" name="name" id="name" pattern=".{3,}" required>
    </div>
    <div class="form-row">
        <label for="email" class="form-label">Email*</label>
        <input type="email" class="form-control" name="email" id="email" required>
    </div>
    <div class="form-row">
        <label for="message" class="form-label">Wiadomość*</label>
        <textarea class="form-control" name="message" id="message" required></textarea>
    </div>
    <div class="form-row">
        <button type="submit" class="button form-submit">
            Wyślij
        </button>
    </div>
</form>

Spróbuj teraz wysłać taki formularz. Zobaczysz, że przeglądarka sama w sobie będzie pokazywać odpowiedni komunikat z błędem danego pola.

Dymki z podpowiedzią pokazują się dopiero w drugim kroku, czyli przy próbie wysłania formularza. Jeżeli chcielibyśmy do naszego formularza dodać dynamiczną podpowiedź w czasie wpisywania, możemy to zrobić za pomocą CSS oraz odpowiedni pseudoklas:

:valid

czy pole jest poprawnie wypełnione

:invalid

czy pole jest źle wypełnione

:user-valid

czy pole jest poprawnie wypełnione, ale po pierwszej interakcji użytkownika z polem

:user-invalid

czy pole jest źle wypełnione, ale po pierwszej interakcji użytkownika z polem

np:

W powyższym kodzie zastosowałem selektory :user-valid i :user-invalid (https://developer.chrome.com/blog/css-wrapped-2023#user-states). Jak zauważysz, ich działanie rozpoczyna się w momencie, gdy użytkownik opuści wypełniane pole (zdarzenie :blur). Są to nowe selektory, dlatego zastanów się, czy aby na pewno będą dobrym wyborem dla twojego projektu (jakie przeglądarki wspiera twój projekt).

Do tej pory przy takiej walidacji mogliśmy korzystać z selektorów :valid i :invalid. Pokazywały one błędy jeszcze przed interakcją użytkownika z polem. Oznaczało to, że użytkownik po wejściu na stronę od razu widział błędnie wypełnione pola. Mogliśmy do obejść np. poprzez dodanie do pola placeholdera np. ze spacją i użycia selektora :placeholder-shown:

Constrains Validation API

Javascript udostępnia nam specjalny interfejs - zwany Constrains Validation API, który bardzo ułatwia walidację formularzy, a który sprzężony jest z powyższym mechanizmem z HTML.

Udostępnia on nam kilka metod i właściwości:

Metody:

input.checkValidity()
sprawdza czy pole jest poprawnie wypełnione. Zwraca true/false, a jeżeli pole jest błędnie wypełnione, odpala dodatkowo event invalid.

form.reportValidity()

Wykonuje sprawdzenie takie jak przy próbie wysłania formularza, który ma walidację w HTML, po czym zwraca true/false. Dla użytkownika oznacza to, że przy pierwszym błędnie wypełnionym polu pojawi się domyślny dymek z komunikatem błędu.

input.setCustomValidity(message)

Pozwala ustawić własny komunikat o błędzie, który pojawia się przy walidacji danego pola

Właściwości:

validity

zawiera obiekt ValidityState, który jest zbiorem właściwości na temat stanu walidacji danego pola (opisane poniżej)

validationMessage

Jeżeli pole podlega walidacji (posiada atrybut required), właściwość ta zawiera aktualną wiadomość, która pojawi się w dymku podczas walidacji. Dla niektórych pól (email, url) wiadomość taka może się zmienić podczas pisania

willValidate

Zwraca true/false w zależności od tego, czy pole będzie sprawdzane

Własna walidacja

Powyżej w czystym HTML za pomocą atrybutów i pól dodaliśmy do naszego formularza walidację.

Ten sam mechanizm możemy wykorzystać w Javascript, dzięki czemu unikniemy pisania dodatkowych testów dla danych pól.

Zanim jednak to zrobimy, powinniśmy wyłączyć domyślne HTMLowe dymki poprzez dodanie do formularza atrybutu novalidate:

Robimy to specjalnie za pomocą Javascript. Dzięki temu osoba z wyłączonym Javascript dostanie domyślną "brzydką" walidację. Jeżeli Javascript zadziała, wtedy użytkownik będzie mógł się cieszyć jej lepszą wersją.

Jeżeli teraz będziemy chcieli sprawdzać pola, które mają nadane odpowiednie atrybuty (required, pattern, type), możemy wykorzystać metodę checkValidity(), która zwraca true/false w zależności od tego, czy dane pole jest wypełnione poprawnie:

Validity State

Każde z pól formularza ma właściwość validity, która wskazuje na obiekt z kilkoma cennymi właściwościami na temat stanu wypełnienia pola:

valid

Zwraca true/false w zależności czy pole przeszło walidację

valueMissing

zwraca true gdy pole wymaga jakiejś wartości, a jej nie podano

typeMismatch

Zwraca true gdy pole jest typu url/email a podana wartość jest błędna (np. do pola email wpisano wartość, która nie jest emailem, a do url wpisano treść nie będącą adresem)

tooShort

Zwraca true jeżeli wpisany tekst jest krótszy niż wartość atrybutu minLength

tooLong

Zwraca true jeżeli wpisany tekst jest dłuższy niż wartość atrybutu maxLength

patternMismatch

Zwraca true jeżeli pole posiada atrybut pattern, a wpisana wartość nie pasuje do niego

badInput

Zwraca true jeżeli wpisana wartość nie może być skonwertowana na wymagany format. Na przykład do pola number wpiszemy tekst nie będący liczbą

stepMismatch

Zwraca true jeżeli pole ma atrybut step, a wartość pola nie pasuje do tego skoku

rangeOverflow

Zwraca true jeżeli pole posiada atrybut max, a podana wartość go przekroczyła

rangeUnderflow

Zwraca true jeżeli pole posiada atrybut min, a podana wartość jest od niego mniejsza

Last updated