Walidacja danych z wykorzystaniem Angulara i Materialize

Walidacja w Angularze

Angular to bardzo mocno rozbudowany framework. Jedną z jego możliwości jest walidacja danych.

Framework monitoruje stan kontrolek (<input>, <textarea>, <select>) i formularzy (<form>). Przechowuje informacje o ich statusie (czy była modyfikacja, czy użytkownik kliknął na nią i czy wpisane dane są poprawne). Angular wykorzystuje atrybuty użyte w HTML5 do walidacji. Oczywiście, możemy zdefiniować własne reguły.

Stan kontrolki

Dzięki Angularowi, w inputach mamy dostęp do takich informacji jak:

  • $untouched- czy użytkownik nie kliknął w kontrolkę.
  • $touched- czy użytkownik kliknął w kontrolkę.
  • $pristine- czy pole nie zostało zmodyfikowane.
  • $dirty- czy pole zostało zmodyfikowane.
  • $valid- czy zawartość spełnia reguły walidacji.
  • $invalid- czy zawartość nie spełnia reguł walidacji.

W <form> są to:

  • $pristine- czy wszystkie pola nie zostały zmodyfikowane.
  • $dirty- czy jakieś pole zostało zmodyfikowane.
  • $valid- czy wszystkie pola w formularzu są zgodne z regułami walidacji.
  • $invalid- czy jakieś pole w formularzu nie jest zgodne z regułami walidacji.
  • $submitted- czy formularz został wysłany.

Wszystkie wymienione wyżej pola przyjmują wartości „true”, albo „false”.

Polecam demo, aby przetestować działanie tych atrybutów.

Władna walidacja

Tworzymy ją za pomocą zdefiniowana dyrektywy. Przykład można znaleźć tutaj.

Walidacja w Materialize

Framework udostępnia nam bardzo ładne (przynajmniej według mnie) zaznaczenie, czy wprowadzone dane są poprawne czy nie.

materialize_validation

Aby skorzystać z tego, wystarczy dodać klasę „validate” do inputa i framework zwaliduje dane według walidacji HTML5.

Co jednak w sytuacji gdy chcemy skorzystać z niestandardowej walidacji i połączyć to z Angularem?

Własna walidacja

Podczas pisania kontrolki rejestracji użytkownika natknąłem się na taki problem. Chciałem by pole potwierdzenia hasła, sprawdzało czy jest ono takie same jak wpisane wyżej hasło. I zaczęły się schody.

form.PNG
Zrzut formularza rejestracji

Kod kontrolek do wpisania hasła:

<div class="input-field col s12">
    <input id="signUpPassword"
           name="password"
           placeholder="Enter password"
           type="password"
           class="validate"
           required
           pattern=".{6,}"
           ng-model="password"/>
<label for="signUpPassword"
           data-error="Password must have at least 6 characters long">
        Password
    </label></div>
<div class="input-field col s12">
    <input id="signUpPasswordConfirm"
           name="passwordConfirm"
           placeholder="Enter password"
           type="password"
           class="validate"
           ng-model="passwordConfirm"
           equals-validation="{{password}}"/>
    <label for="signUpPasswordConfirm"
           data-error="Diffrent passwords">
        Confrim Password
    </label></div>

Angular nie ma wbudowanej takiej funkcjonalności, więc trzeba napisać samemu dyrektywę. Chwila szukania na stacku i gotowe.

Trzeba jeszcze jeszcze jakoś poinformować framework Materialize, że wartość jest błędna lub poprawna. Można to osiągnąć ustawiając odpowiednio klasę „invalid” lub „valid” na kontrolce. Jednak to rozwiązanie nie do końca działa. Kontrolka po straceniu focusa, jest ponownie walidowana za pomocą reguł HTML5. Input miał tylko ustawiony atrybut „required”, więc sprawdzane było, czy jest jakiś tekst, który nie musi być zgodny z wpisanym wyżej hasłem. Obejściem tego jest, podpięcie się w dyrektywie do zdarzenia „blur” (stracenie focusa) i wykonanie ponownie walidacji.

deadlineApp.directive("equalsValidation",
    function() {
        return {
            restrict: "A",
            require: "ngModel",
            link: function(scope, elem, attrs, ngModel) {
                var validate = function() {
                    const val1 = ngModel.$viewValue;
                    const val2 = attrs.equalsValidation;
                    const isValid = !val1 || !val2 || val1 === val2;
                    ngModel.$setValidity("equals", isValid);
                    if (val1) {
                        if (isValid) {
                            elem.removeClass("invalid").addClass("valid");
                        } else {
                            elem.removeClass("valid").addClass("invalid");
                        }
                    } else {
                        elem.removeClass("valid").removeClass("invalid");
                    }
               };

               elem.bind("blur", validate);

               scope.$watch(attrs.ngModel,
                   function() {
                       validate();
                   });

               attrs.$observe("equalsValidation",
                   function(val) {
                       validate();
                   });
        }
    }
 });
Reklamy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s