You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/bg/7-bank-project/2-forms
Lee Stott 2daab5271b
Update Quiz Link
3 weeks ago
..
README.md Update Quiz Link 3 weeks ago
assignment.md 🌐 Update translations via Co-op Translator 3 weeks ago

README.md

Създаване на Банкова Приложение Част 2: Създаване на Формуляр за Вход и Регистрация

Предварителен Тест

Предварителен тест

Въведение

В почти всички съвременни уеб приложения можете да създадете акаунт, за да имате свое собствено лично пространство. Тъй като множество потребители могат да имат достъп до уеб приложението едновременно, е необходим механизъм за съхранение на личните данни на всеки потребител отделно и за избор на информацията, която да се показва. Няма да разглеждаме как да управляваме потребителската идентичност сигурно, тъй като това е обширна тема сама по себе си, но ще се уверим, че всеки потребител може да създаде един (или повече) банкови акаунти в нашето приложение.

В тази част ще използваме HTML формуляри, за да добавим вход и регистрация към нашето уеб приложение. Ще видим как да изпращаме данни към сървърна API програмно и в крайна сметка как да дефинираме основни правила за валидиране на потребителски вход.

Предварителни изисквания

Трябва да сте завършили HTML шаблони и маршрутизация на уеб приложението за този урок. Също така трябва да инсталирате Node.js и да стартирате сървърната API локално, за да можете да изпращате данни за създаване на акаунти.

Обърнете внимание Ще имате два терминала, работещи едновременно, както е описано по-долу:

  1. За основното банково приложение, което създадохме в урока HTML шаблони и маршрутизация
  2. За сървърната API на Банковото Приложение, която току-що настроихме.

Трябва да стартирате и двата сървъра, за да продължите с останалата част от урока. Те слушат на различни портове (порт 3000 и порт 5000), така че всичко трябва да работи без проблеми.

Можете да тествате дали сървърът работи правилно, като изпълните тази команда в терминала:

curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result

Формуляр и контроли

Елементът <form> обхваща секция от HTML документ, където потребителят може да въвежда и изпраща данни чрез интерактивни контроли. Съществуват всякакви потребителски интерфейсни (UI) контроли, които могат да се използват в рамките на формуляр, като най-често срещаните са елементите <input> и <button>.

Има много различни типове <input>, например за създаване на поле, където потребителят може да въведе своето потребителско име, можете да използвате:

<input id="username" name="username" type="text">

Атрибутът name ще се използва като име на свойството, когато данните от формуляра бъдат изпратени. Атрибутът id се използва за асоцииране на <label> с контролата на формуляра.

Разгледайте целия списък с <input> типове и други контроли на формуляри, за да получите представа за всички вградени UI елементи, които можете да използвате при изграждането на вашия интерфейс.

Забележете, че <input> е празен елемент, на който не трябва да добавяте съответстващ затварящ таг. Можете обаче да използвате самозатварящата се нотация <input/>, но това не е задължително.

Елементът <button> в рамките на формуляр е малко специален. Ако не зададете неговия атрибут type, той автоматично ще изпрати данните от формуляра към сървъра, когато бъде натиснат. Ето възможните стойности на type:

  • submit: По подразбиране в рамките на <form>, бутонът задейства действието за изпращане на формуляра.
  • reset: Бутонът нулира всички контроли на формуляра до техните начални стойности.
  • button: Не задава никакво поведение по подразбиране, когато бутонът бъде натиснат. Можете да му зададете персонализирани действия с помощта на JavaScript.

Задача

Нека започнем с добавяне на формуляр към шаблона login. Ще ни трябва поле за потребителско име и бутон Вход.

<template id="login">
  <h1>Bank App</h1>
  <section>
    <h2>Login</h2>
    <form id="loginForm">
      <label for="username">Username</label>
      <input id="username" name="user" type="text">
      <button>Login</button>
    </form>
  </section>
</template>

Ако погледнете по-отблизо, можете да забележите, че тук сме добавили и елемент <label>. Елементите <label> се използват за добавяне на име към UI контроли, като нашето поле за потребителско име. Етикетите са важни за четимостта на вашите формуляри, но също така идват с допълнителни предимства:

  • Чрез асоцииране на етикет с контрола на формуляра, това помага на потребителите, използващи асистивни технологии (като екранен четец), да разберат какви данни се очаква да предоставят.
  • Можете да кликнете върху етикета, за да поставите директно фокуса върху свързаното поле, което улеснява достъпа на устройства с тъчскрийн.

Достъпността в уеб пространството е много важна тема, която често се пренебрегва. Благодарение на семантичните HTML елементи не е трудно да създадете достъпно съдържание, ако ги използвате правилно. Можете да прочетете повече за достъпността, за да избегнете често срещани грешки и да станете отговорен разработчик.

Сега ще добавим втори формуляр за регистрация, точно под предишния:

<hr/>
<h2>Register</h2>
<form id="registerForm">
  <label for="user">Username</label>
  <input id="user" name="user" type="text">
  <label for="currency">Currency</label>
  <input id="currency" name="currency" type="text" value="$">
  <label for="description">Description</label>
  <input id="description" name="description" type="text">
  <label for="balance">Current balance</label>
  <input id="balance" name="balance" type="number" value="0">
  <button>Register</button>
</form>

С помощта на атрибута value можем да дефинираме стойност по подразбиране за дадено поле. Забележете също, че полето за balance има тип number. Изглежда ли различно от другите полета? Опитайте да взаимодействате с него.

Можете ли да навигирате и взаимодействате с формулярите само с клавиатура? Как бихте направили това?

Изпращане на данни към сървъра

Сега, когато имаме функционален интерфейс, следващата стъпка е да изпратим данните към сървъра. Нека направим бърз тест с текущия код: какво се случва, ако кликнете върху бутона Вход или Регистрация?

Забелязахте ли промяната в секцията на URL адреса на браузъра?

Снимка на екрана, показваща промяна в URL адреса на браузъра след клик върху бутона Регистрация

По подразбиране действието на <form> е да изпрати формуляра към текущия URL адрес на сървъра, използвайки GET метода, като добавя данните от формуляра директно към URL адреса. Този метод обаче има някои недостатъци:

  • Изпратените данни са много ограничени по размер (около 2000 символа)
  • Данните са директно видими в URL адреса (не е подходящо за пароли)
  • Не работи с качване на файлове

Затова можете да го промените, за да използва POST метода, който изпраща данните от формуляра към сървъра в тялото на HTTP заявката, без предишните ограничения.

Въпреки че POST е най-често използваният метод за изпращане на данни, в някои специфични сценарии е за предпочитане да се използва GET методът, например при имплементиране на поле за търсене.

Задача

Добавете свойства action и method към формуляра за регистрация:

<form id="registerForm" action="//localhost:5000/api/accounts" method="POST">

Сега опитайте да регистрирате нов акаунт с вашето име. След като кликнете върху бутона Регистрация, трябва да видите нещо подобно:

Прозорец на браузъра на адрес localhost:5000/api/accounts, показващ JSON низ с потребителски данни

Ако всичко върви добре, сървърът трябва да отговори на вашата заявка с JSON отговор, съдържащ данните за създадения акаунт.

Опитайте да се регистрирате отново със същото име. Какво се случва?

Изпращане на данни без презареждане на страницата

Както вероятно забелязахте, има малък проблем с подхода, който току-що използвахме: при изпращане на формуляра излизаме от нашето приложение и браузърът се пренасочва към URL адреса на сървъра. Опитваме се да избегнем всички презареждания на страницата с нашето уеб приложение, тъй като създаваме Едностранично приложение (SPA).

За да изпратим данните от формуляра към сървъра без да принуждаваме презареждане на страницата, трябва да използваме JavaScript код. Вместо да поставяме URL адрес в свойството action на елемента <form>, можете да използвате произволен JavaScript код, предшестван от низа javascript:, за да изпълните персонализирано действие. Използването на това означава също, че ще трябва да имплементирате някои задачи, които преди това се извършваха автоматично от браузъра:

  • Извличане на данните от формуляра
  • Конвертиране и кодиране на данните от формуляра в подходящ формат
  • Създаване на HTTP заявка и изпращането й към сървъра

Задача

Заменете action на формуляра за регистрация със:

<form id="registerForm" action="javascript:register()">

Отворете app.js и добавете нова функция с име register:

function register() {
  const registerForm = document.getElementById('registerForm');
  const formData = new FormData(registerForm);
  const data = Object.fromEntries(formData);
  const jsonData = JSON.stringify(data);
}

Тук извличаме елемента на формуляра, използвайки getElementById() и използваме помощника FormData, за да извлечем стойностите от контролите на формуляра като набор от ключ/стойност двойки. След това конвертираме данните в обикновен обект, използвайки Object.fromEntries(), и накрая сериализираме данните в JSON, формат, който често се използва за обмен на данни в уеб пространството.

Данните вече са готови за изпращане към сървъра. Създайте нова функция с име createAccount:

async function createAccount(account) {
  try {
    const response = await fetch('//localhost:5000/api/accounts', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: account
    });
    return await response.json();
  } catch (error) {
    return { error: error.message || 'Unknown error' };
  }
}

Какво прави тази функция? Първо, забележете ключовата дума async тук. Това означава, че функцията съдържа код, който ще се изпълнява асинхронно. Когато се използва заедно с ключовата дума await, тя позволява изчакване за изпълнение на асинхронен код - като изчакване за отговор от сървъра тук - преди да продължи.

Ето кратко видео за използването на async/await:

Async и Await за управление на обещания

🎥 Кликнете върху изображението по-горе за видео за async/await.

Използваме API-то fetch(), за да изпратим JSON данни към сървъра. Този метод приема 2 параметъра:

  • URL адреса на сървъра, затова тук поставяме //localhost:5000/api/accounts.
  • Настройките на заявката. Тук задаваме метода на POST и предоставяме body за заявката. Тъй като изпращаме JSON данни към сървъра, трябва също да зададем заглавката Content-Type на application/json, за да може сървърът да интерпретира съдържанието.

Тъй като сървърът ще отговори на заявката с JSON, можем да използваме await response.json(), за да анализираме JSON съдържанието и да върнем получения обект. Забележете, че този метод е асинхронен, затова използваме ключовата дума await тук, преди да върнем, за да се уверим, че всички грешки по време на анализа също са уловени.

Сега добавете малко код към функцията register, за да извикате createAccount():

const result = await createAccount(jsonData);

Тъй като използваме ключовата дума await тук, трябва да добавим ключовата дума async преди функцията register:

async function register() {

Накрая, нека добавим някои логове, за да проверим резултата. Финалната функция трябва да изглежда така:

async function register() {
  const registerForm = document.getElementById('registerForm');
  const formData = new FormData(registerForm);
  const jsonData = JSON.stringify(Object.fromEntries(formData));
  const result = await createAccount(jsonData);

  if (result.error) {
    return console.log('An error occurred:', result.error);
  }

  console.log('Account created!', result);
}

Това беше малко дълго, но стигнахме до целта! Ако отворите инструментите за разработчици на браузъра и опитате да регистрирате нов акаунт, не трябва да виждате никаква промяна на уеб страницата, но съобщение ще се появи в конзолата, потвърждавайки, че всичко работи.

Снимка на екрана, показваща съобщение в конзолата на браузъра

Смятате ли, че данните се изпращат към сървъра сигурно? Какво би станало, ако някой успее да прихване заявката? Можете да прочетете за HTTPS, за да научите повече за сигурната комуникация на данни.

Валидиране на данни

Ако опитате да регистрирате нов акаунт, без да зададете потребителско име, можете да видите, че сървърът връща грешка със статус код 400 (Bad Request).

Преди да изпращате данни към сървъра, е добра практика да валидирате данните от формуляра предварително, когато е възможно, за да се уверите, че изпращате валидна заявка. HTML5 контролите на формуляра предоставят вградена валидиране, използвайки различни атрибути:

  • required: полето трябва да бъде попълнено, иначе формулярът не може да бъде изпратен.
  • minlength и maxlength: дефинират минималния и максималния брой символи в текстови полета.
  • min и max: дефинират минималната и максималната стойност на числово поле.
  • type: дефинира вида на очакваните данни, като number, email, file или други вградени типове. Този атрибут може също да промени визуалното представяне на контролата на формуляра.
  • pattern: позволява дефиниране на [регулярен израз](https

Съвет: можете да персонализирате външния вид на вашите контролни елементи във формуляра в зависимост от това дали са валидни или не, като използвате CSS псевдокласовете :valid и :invalid.

Задача

Има два задължителни полета за създаване на валиден нов акаунт: потребителско име и валута. Останалите полета са по избор. Актуализирайте HTML формуляра, като използвате както атрибута required, така и текст в етикета на полето, за да:

<label for="user">Username (required)</label>
<input id="user" name="user" type="text" required>
...
<label for="currency">Currency (required)</label>
<input id="currency" name="currency" type="text" value="$" required>

Въпреки че тази конкретна сървърна имплементация не налага специфични ограничения за максималната дължина на полетата, винаги е добра практика да се задават разумни ограничения за всяко текстово поле, което потребителят попълва.

Добавете атрибут maxlength към текстовите полета:

<input id="user" name="user" type="text" maxlength="20" required>
...
<input id="currency" name="currency" type="text" value="$" maxlength="5" required>
...
<input id="description" name="description" type="text" maxlength="100">

Сега, ако натиснете бутона Регистрация и някое поле не отговаря на зададените правила за валидация, ще видите нещо подобно:

Екранна снимка, показваща грешка при валидация при опит за изпращане на формуляра

Валидацията, която се извършва преди изпращането на данни към сървъра, се нарича клиентска валидация. Но имайте предвид, че не винаги е възможно да се извършат всички проверки без изпращане на данни. Например, тук не можем да проверим дали вече съществува акаунт със същото потребителско име, без да изпратим заявка към сървъра. Допълнителната валидация, която се извършва на сървъра, се нарича сървърна валидация.

Обикновено и двете трябва да бъдат имплементирани. Клиентската валидация подобрява потребителското изживяване, като предоставя незабавна обратна връзка, но сървърната валидация е от съществено значение, за да се гарантира, че данните, които обработвате, са коректни и безопасни.


🚀 Предизвикателство

Покажете съобщение за грешка в HTML, ако потребителят вече съществува.

Ето пример как може да изглежда финалната страница за вход след малко стилизиране:

Екранна снимка на страницата за вход след добавяне на CSS стилове

Тест след лекцията

Тест след лекцията

Преглед и самостоятелно обучение

Разработчиците са станали много креативни в усилията си за създаване на формуляри, особено по отношение на стратегиите за валидация. Научете повече за различни подходи към формулярите, като разгледате CodePen; можете ли да намерите интересни и вдъхновяващи примери?

Задание

Стилизирайте вашето банково приложение


Отказ от отговорност:
Този документ е преведен с помощта на AI услуга за превод Co-op Translator. Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.