AngularJS – Formularze

bugajsky.pl 6 lat temu

Ten wpis będzie o tworzeniu formularzy, wykorzystując framework AngularJS. Prosta aplikacja, zbudowana na bazie dwóch komponentów posłuży nam do zademonstrowania, w jaki sposób powinniśmy tworzyć i walidować formularze, powszechnie wykorzystywane w tworzonych systemach webowych.

Część teoretyczna

Aplikacje internetowe wykorzystują formularze do wprowadzania danych, zatem są istotną częścią aplikacji. Walidacja wprowadzanych danych przez użytkowników powinna się odbywać zarówno po stronie klienta, jak również serwera. Aby ominięcie zabezpieczeń w aplikacji klienckiej nie spowodowało problemów po stronie serwera.

AngularJS umożliwia nam obsługę formularzy na podstawie HTMLowego znacznika <form>, a także dzięki dyrektywy Angularowej ngForm. Utworzona dyrektywa przez twórców frameworka, daje nam możliwość obsługi zagnieżdżonych formularzy. Zarówno wykorzystanie znacznika, jak i dyrektywy daje nam dostęp do obiektu powiązanego z danym formularzem. Obiekt ten przechowuje informacje wykorzystywane do walidacji. Abyśmy mogli korzystać z tego obiektu, należy do znacznika <form> lub <ng-form> dodać atrybut name.

Pola obiektu

$pristine – wartość typu boolean jeżeli formularz nie został zmieniony zwracana wartość true, po zmianie któregokolwiek pola wartość zostaje zmieniona na false.
$dirty
– wartość typu boolean to odwrotność pola $pristine, zatem jeżeli pole nie zostało zmienione zwraca wartość false, po zmienie minimum jednego pola wartość zostaje zmieniona na true.
$valid – wartość typu boolean zwraca wartość true, jeżeli wszystkie pola formularza zostały poprawnie wypełnione, w przeciwnym wypadku zwracana wartość to false.
$invalid – wartość typu boolean zwraca odwrotność pola $valid.
$submitted – wartość typu boolean zwraca true, jeżeli użytkownik wysłał formularz, w przeciwnym wypadku wartość tego pola to false.
$error – wartość typu Object odwołuje się do pól, które nie przeszły poprawnie walidacji.

Pola tego obiektu dają nam możliwość zweryfikowania wprowadzonych danych przez użytkownika.

Przykładowa aplikacja

Na potrzeby tego wpisu przygotujemy aplikację, która będzie zbudowana z dwóch komponentów. Pierwszy z nich odpowiada za wprowadzanie danych, drugi zaś za wyświetlanie wcześniej wprowadzonych danych.

index.html

<!DOCTYPE html> <html lang="pl" ng-app="app"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>AngularJS #10</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> .panel-default { margin-top: 2em; padding: 1em; } .btn { width: 100% } .control-form { width: 100% } .inupt-text { margin-bottom: 1em; width: 100%; } .error { color: red; } </style> </head> <body ng-controller="appController as appCtrl"> <div> <div> <form-register register="appCtrl.register" ng-if="!appCtrl.register.formCheck"></form-register> <register-profil data="appCtrl.register" ng-if="appCtrl.register.formCheck"></register-profil> </div> </div> <script src="https://code.jquery.com/jquery-3.2.1.slim.js" integrity="sha256-tA8y0XqiwnpwmOIl3SGAcFl2RvxHjA8qp0+1uCGmRmg=" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script> <script> var app = angular.module("app", []); app.controller('appController', function () { var ctrl = this; ctrl.register = {}; ctrl.register.formCheck = false; }); app.component('formRegister', { templateUrl: 'formRegister.html', bindings: { register: '=' }, controller: formRegisterController }); app.component('registerProfil', { templateUrl: 'registerProfil.html', bindings: { data: '<' } }); function formRegisterController() { var ctrl = this; ctrl.submit = function () { ctrl.register.formCheck = true; } } </script> </body> </html>

formRegister.html

<div> <h1>Register</h1> <form name="formReg"> <div> <label for="mail">Email address</label> <label ng-show="formReg.registerEmail.$touched && formReg.registerEmail.$invalid">Correct the e-mail address</label> <input type="email" id="mail" placeholder="Email" name="registerEmail" ng-model="$ctrl.register.email" required> </div> <div> <label for="passwd">Password</label> <label ng-show="formReg.registerPasswd.$touched && formReg.registerPasswd.$invalid">Please correct the password</label> <input type="password" id="passwd" placeholder="Password" name="registerPasswd" ng-model="$ctrl.register.passwd" required> </div> <div> <label for="rpasswd">Repeat password</label> <label ng-show="formReg.registerRPasswd.$touched && formReg.registerRPasswd.$invalid">The repeated password doesn't match</label> <input type="password" id="rpasswd" placeholder="Repeat password" name="registerRPasswd" ng-model="$ctrl.register.rpasswd" required> </div> <div> <label> <input type="checkbox" ng-model="$ctrl.register.conditions" name="registerCond" required> I agree to terms and conditions </label> </div> <button type="submit" ng-click="$ctrl.submit()" ng-disabled="formReg.$invalid || $ctrl.register.passwd !== $ctrl.register.rpasswd">Register</button> </form> </div>

registerProfil.html

<h1>Zarejestronwano</h1> <p> <strong>Emial: </strong>{{$ctrl.data.email}} </p> <p> <strong>Password: </strong>{{$ctrl.data.passwd}} </p> <p> <strong>Accepted Conditions: </strong>{{$ctrl.data.conditions}} </p>

Aplikacja składa się z 3 plików: index.html zawiera kod html strony głównej, a także obsługę AngularJS, formRegister.html którego zadaniem jest przechowywanie kodu html komponentu <form-register> odpowiedzialnego za wprowadzanie danych oraz registerProfil.html, który odpowiada za przechowywanie kodu html komponentu <register-profil>, którego zadaniem jest wyświetlanie wprowadzonych danych w formularzu przez użytkownika.

Omówienie index.html

Przejdźmy do omówienia tego co dzieje się w naszej aplikacji. Na początku tworzymy w pliku index.html moduł naszej Angularowej aplikacji. Następnym krokiem jest utworzenie kontrolera naszej aplikacji, którego zadaniem będzie przechowywanie danych i przekazywanie ich do utworzonych przez nas komponentów.

ctrl.register = {}; ctrl.register.formCheck = false;

Kontroler ten zawiera obiekt register, do którego będą przekazywane dane z formularza, a także pole w tym obiekcie formCheck, wykorzystywane do sprawdzenia warunków wyświetlania utworzonych przez nas komponentów.

Kolejnym krokiem jest utworzenie komponentów. Pierwszym jaki tworzymy jest formRegister. O tworzeniu komponentów można przeczytać w jednym z wcześniejszych wpisów AngularJS – Component. dzięki templateUrl ustawiamy szablon html komponentu, bindings odpowiada za określenie przekazywanych danych, zaś ostatnie pole obiektu konfiguracyjnego przypisuje komponentowi kontroler, odpowiedzialny za wykonywanie operacji na danych.

ctrl.register.formCheck = true;

W przypisanym kontrolerze mamy utworzoną funkcję submit(), odpowiedzialną za zmianę wartości pola formCheck obiektu register.

W podobny sposób tworzymy komponent wykorzystywany do wyświetlania wprowadzonych danych przez użytkownika. Określamy szablon html, a także przekazywane dane do komponentu.

Omówienie formRegister.html

Przejdźmy teraz do pliku formRegister.html, bo tu dzieje się najwięcej.

<form name="formReg">

Do znacznika <form> dodajemy atrybut name, za pomocą którego będziemy mogli się odwoływać do obiektu opisanego powyżej.

Następnie mamy 4 kontrolki oraz przycisk odpowiedzialny za wysłanie danych.

<div> <label for="mail">Email address</label> <label ng-show="formReg.registerEmail.$touched && formReg.registerEmail.$invalid">Correct the e-mail address</label> <input type="email" id="mail" placeholder="Email" name="registerEmail" ng-model="$ctrl.register.email" required> </div>

Zacznijmy omawianie pierwszego elementu formularza od końca, czyli od znacznika <input>. Mamy określony atrybut type, który jest odpowiedzialny za sprawdzanie czy podany ciąg znaków jest adresem email. Przypisanie klasy css dzięki atrybutu class. Kolejne atrybuty to: id oraz placeholder. Atrybut name w danym polu wykorzystywane jest do walidacji tego pola. ng-model odpowiada za wiązanie dwukierunkowe danych.

Po określeniu inputu możemy przystąpić do wyświetlania komunikatu o błędzie. Do tego wykorzystywany jest znacznik <label> z klasą error. Najważniejsza tutaj jest dyrektywa ng-show, która to określa warunek, kiedy ma zostać wyświetlony komunikat. Pojawia się jeżeli pole zostało naciśnięte, ale w tej chwili jest już opuszczone i pole nie jest poprawnie wypełnione.

Jak możemy zauważyć, mamy tutaj zaprezentowany schemat odwoływania się do pól sprawdzających pole formularza. Schemat ten wygląda następująco:

nazwa_formularza._nazwa_pola.$pole_obiektu

W podobny sposób zrealizowane są kolejne pola formularza. Kolejną walidację mamy przy przycisku. Sprawdzamy tam, czy formularz został wypełniony prawidłowo, jeżeli tak umożliwiamy wysłanie go na serwer.

<button type="submit" ng-click="$ctrl.submit()" ng-disabled="formReg.$invalid || $ctrl.register.passwd !== $ctrl.register.rpasswd">Register</button>

Odpowiada za to dyrektywa ng-disabled, która ma możliwość łączenia warunków jedynie dzięki spójnika lub ||. Sprawdzamy tutaj czy wszystkie pola zostały wypełnione, a także czy hasło oraz powtórzone hasło są różne. jeżeli któryś z warunków jest spełniony, blokowana jest możliwość przesłania formularza.

Szablon dla komponentu registerProfil to proste wyświetlanie danych przekazanych jako atrybut komponentu.

Efekt działania aplikacji

Podsumowanie

Stworzona przez nas aplikacja prezentuje sposób tworzenia i sprawdzania poprawności wprowadzonych danych przez użytkownika przy pomocy AngularJS. Jak widzimy, walidacja formularzy z wykorzystaniem frameworka jest bardzo prosta i przejrzysta. To kolejny krok postawiony w nauce tej biblioteki. W kolejnych wpisach zajmiemy się dalszymi elementami wykorzystywanymi podczas pisania aplikacji.

Idź do oryginalnego materiału