# Izdelava bančne aplikacije, 2. del: Prijavni in registracijski obrazec ## Predhodni kviz [Predhodni kviz](https://ff-quizzes.netlify.app/web/quiz/43) ### Uvod Skoraj vse sodobne spletne aplikacije omogočajo ustvarjanje računa za osebni prostor. Ker lahko več uporabnikov hkrati dostopa do spletne aplikacije, potrebujete mehanizem za ločeno shranjevanje osebnih podatkov vsakega uporabnika in izbiro, katere informacije prikazati. Ne bomo se poglabljali v [varno upravljanje identitete uporabnikov](https://en.wikipedia.org/wiki/Authentication), saj je to obsežna tema, vendar bomo poskrbeli, da bo vsak uporabnik lahko ustvaril enega (ali več) bančnih računov v naši aplikaciji. V tem delu bomo uporabili HTML obrazce za dodajanje prijave in registracije v našo spletno aplikacijo. Naučili se bomo, kako podatke programatično poslati strežniškemu API-ju, ter kako določiti osnovna pravila za validacijo uporabniških vnosov. ### Predpogoji Za to lekcijo morate dokončati [HTML predloge in usmerjanje](../1-template-route/README.md) spletne aplikacije. Prav tako morate namestiti [Node.js](https://nodejs.org) in [zagnati strežniški API](../api/README.md) lokalno, da lahko pošiljate podatke za ustvarjanje računov. **Pomembno** Hkrati boste morali imeti odprta dva terminala, kot je navedeno spodaj: 1. Za glavno bančno aplikacijo, ki smo jo izdelali v lekciji [HTML predloge in usmerjanje](../1-template-route/README.md) 2. Za [strežniški API bančne aplikacije](../api/README.md), ki smo ga pravkar nastavili zgoraj. Oba strežnika morata biti zagnana, da lahko sledite preostanku lekcije. Strežnika poslušata na različnih vratih (vrata `3000` in vrata `5000`), zato bi moralo vse delovati brez težav. Delovanje strežnika lahko preverite z naslednjim ukazom v terminalu: ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## Obrazec in kontrolniki Element `
` zajema del HTML dokumenta, kjer lahko uporabnik vnese in pošlje podatke z interaktivnimi kontrolniki. Obstaja veliko različnih uporabniških vmesnikov (UI) kontrolnikov, ki jih lahko uporabite znotraj obrazca, najpogostejša pa sta elementa `` in `
``` Z uporabo atributa `value` lahko določimo privzeto vrednost za določeno polje. Opazite tudi, da ima polje za `balance` tip `number`. Ali izgleda drugače kot ostala polja? Poskusite interakcijo z njim. ✅ Ali lahko obrazce uporabljate in se po njih premikate samo s tipkovnico? Kako bi to storili? ## Pošiljanje podatkov na strežnik Sedaj, ko imamo funkcionalni UI, je naslednji korak pošiljanje podatkov na strežnik. Naredimo hiter test z našo trenutno kodo: kaj se zgodi, če kliknete na gumb *Prijava* ali *Registracija*? Ste opazili spremembo v URL-ju vašega brskalnika? ![Posnetek zaslona spremembe URL-ja brskalnika po kliku na gumb Registracija](../../../../translated_images/click-register.e89a30bf0d4bc9ca867dc537c4cea679a7c26368bd790969082f524fed2355bc.sl.png) Privzeto dejanje za `
` je pošiljanje obrazca na trenutni URL strežnika z uporabo [GET metode](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3), pri čemer se podatki obrazca neposredno dodajo URL-ju. Ta metoda ima nekaj pomanjkljivosti: - Poslani podatki so zelo omejeni po velikosti (približno 2000 znakov) - Podatki so neposredno vidni v URL-ju (ni idealno za gesla) - Ne deluje z nalaganjem datotek Zato lahko spremenite metodo na [POST](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5), ki pošlje podatke obrazca na strežnik v telesu HTTP zahteve, brez prejšnjih omejitev. > Čeprav je POST najpogosteje uporabljena metoda za pošiljanje podatkov, je [v nekaterih specifičnih scenarijih](https://www.w3.org/2001/tag/doc/whenToUseGet.html) bolje uporabiti metodo GET, na primer pri implementaciji iskalnega polja. ### Naloga Dodajte lastnosti `action` in `method` obrazcu za registracijo: ```html ``` Sedaj poskusite registrirati nov račun z vašim imenom. Po kliku na gumb *Registracija* bi morali videti nekaj takega: ![Okno brskalnika na naslovu localhost:5000/api/accounts, ki prikazuje JSON niz s podatki uporabnika](../../../../translated_images/form-post.61de4ca1b964d91a9e338416e19f218504dd0af5f762fbebabfe7ae80edf885f.sl.png) Če gre vse po načrtih, bi moral strežnik odgovoriti na vašo zahtevo z [JSON](https://www.json.org/json-en.html) odzivom, ki vsebuje podatke o ustvarjenem računu. ✅ Poskusite se ponovno registrirati z istim imenom. Kaj se zgodi? ## Pošiljanje podatkov brez osveževanja strani Kot ste verjetno opazili, je pri pristopu, ki smo ga pravkar uporabili, majhna težava: ob pošiljanju obrazca zapustimo našo aplikacijo in brskalnik preusmeri na URL strežnika. Poskušamo se izogniti vsem osvežitvam strani v naši spletni aplikaciji, saj izdelujemo [enostransko aplikacijo (SPA)](https://en.wikipedia.org/wiki/Single-page_application). Da pošljemo podatke obrazca na strežnik brez prisilnega osveževanja strani, moramo uporabiti JavaScript kodo. Namesto da v lastnost `action` elementa `` vnesemo URL, lahko uporabimo katerokoli JavaScript kodo, ki ji predhodimo z nizom `javascript:`, da izvedemo prilagojeno dejanje. Uporaba tega pomeni, da boste morali sami implementirati nekatere naloge, ki jih je prej samodejno opravil brskalnik: - Pridobitev podatkov obrazca - Pretvorba in kodiranje podatkov obrazca v ustrezen format - Ustvarjanje HTTP zahteve in pošiljanje na strežnik ### Naloga Zamenjajte lastnost `action` obrazca za registracijo z: ```html ``` Odprite `app.js` in dodajte novo funkcijo z imenom `register`: ```js function register() { const registerForm = document.getElementById('registerForm'); const formData = new FormData(registerForm); const data = Object.fromEntries(formData); const jsonData = JSON.stringify(data); } ``` Tukaj pridobimo element obrazca z uporabo `getElementById()` in uporabimo pripomoček [`FormData`](https://developer.mozilla.org/docs/Web/API/FormData) za pridobitev vrednosti iz kontrolnikov obrazca kot nabor ključ/vrednost parov. Nato podatke pretvorimo v običajen objekt z uporabo [`Object.fromEntries()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries) in jih na koncu serializiramo v [JSON](https://www.json.org/json-en.html), format, ki se pogosto uporablja za izmenjavo podatkov na spletu. Podatki so sedaj pripravljeni za pošiljanje na strežnik. Ustvarite novo funkcijo z imenom `createAccount`: ```js 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' }; } } ``` Kaj počne ta funkcija? Najprej opazite ključni besedi `async` tukaj. To pomeni, da funkcija vsebuje kodo, ki se bo izvajala [**asinhrono**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). Ko jo uporabimo skupaj s ključnimi besedami `await`, omogoča čakanje na izvajanje asinhrone kode - na primer čakanje na odgovor strežnika - preden nadaljujemo. Tukaj je kratek video o uporabi `async/await`: [![Async in Await za upravljanje obljub](https://img.youtube.com/vi/YwmlRkrxvkk/0.jpg)](https://youtube.com/watch?v=YwmlRkrxvkk "Async in Await za upravljanje obljub") > 🎥 Kliknite zgornjo sliko za video o async/await. Uporabimo API `fetch()` za pošiljanje JSON podatkov na strežnik. Ta metoda sprejme 2 parametra: - URL strežnika, zato tukaj ponovno vnesemo `//localhost:5000/api/accounts`. - Nastavitve zahteve. Tukaj nastavimo metodo na `POST` in zagotovimo `body` za zahtevo. Ker pošiljamo JSON podatke na strežnik, moramo nastaviti tudi glavo `Content-Type` na `application/json`, da strežnik ve, kako interpretirati vsebino. Ker bo strežnik odgovoril na zahtevo z JSON, lahko uporabimo `await response.json()` za razčlenitev JSON vsebine in vrnitev rezultirajočega objekta. Upoštevajte, da je ta metoda asinhrona, zato tukaj uporabimo ključni besedi `await`, da zagotovimo, da so morebitne napake med razčlenitvijo tudi zajete. Sedaj dodajte nekaj kode v funkcijo `register`, da pokličete `createAccount()`: ```js const result = await createAccount(jsonData); ``` Ker tukaj uporabljamo ključni besedi `await`, moramo dodati ključni besedi `async` pred funkcijo register: ```js async function register() { ``` Na koncu dodajmo nekaj zapisov za preverjanje rezultata. Končna funkcija bi morala izgledati takole: ```js 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); } ``` To je bilo nekoliko daljše, vendar smo prišli do cilja! Če odprete [orodja za razvijalce brskalnika](https://developer.mozilla.org/docs/Learn/Common_questions/What_are_browser_developer_tools) in poskusite registrirati nov račun, ne bi smeli opaziti nobene spremembe na spletni strani, vendar se bo v konzoli prikazalo sporočilo, ki potrjuje, da vse deluje. ![Posnetek zaslona, ki prikazuje sporočilo v konzoli brskalnika](../../../../translated_images/browser-console.efaf0b51aaaf67782a29e1a0bb32cc063f189b18e894eb5926e02f1abe864ec2.sl.png) ✅ Ali menite, da so podatki poslani na strežnik varno? Kaj če bi nekdo prestregel zahtevo? Več o [HTTPS](https://en.wikipedia.org/wiki/HTTPS) lahko preberete, da se naučite več o varni komunikaciji podatkov. ## Validacija podatkov Če poskusite registrirati nov račun brez vnosa uporabniškega imena, lahko vidite, da strežnik vrne napako s statusno kodo [400 (Slaba zahteva)](https://developer.mozilla.org/docs/Web/HTTP/Status/400#:~:text=The%20HyperText%20Transfer%20Protocol%20(HTTP,%2C%20or%20deceptive%20request%20routing).). Pred pošiljanjem podatkov na strežnik je dobra praksa, da [validirate podatke obrazca](https://developer.mozilla.org/docs/Learn/Forms/Form_validation) vnaprej, kadar je to mogoče, da zagotovite, da pošiljate veljavno zahtevo. HTML5 kontrolniki obrazcev omogočajo vgrajeno validacijo z uporabo različnih atributov: - `required`: polje mora biti izpolnjeno, sicer obrazca ni mogoče poslati. - `minlength` in `maxlength`: določata minimalno in maksimalno število znakov v besedilnih poljih. - `min` in `max`: določata minimalno in maksimalno vrednost numeričnega polja. - `type`: določa vrsto pričakovanih podatkov, kot so `number`, `email`, `file` ali [druge vgrajene vrste](https://developer.mozilla.org/docs/Web/HTML/Element/input). Ta atribut lahko spremeni tudi vizualni prikaz kontrolnika obrazca. - `pattern`: omogoča določitev [regularnega izraza](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Regular_Expressions) za preverjanje, ali so vneseni podatki veljavni ali ne. Namig: videz kontrolnikov obrazca lahko prilagodite glede na to, ali so veljavni ali ne, z uporabo CSS psevdo-razredov `:valid` in `:invalid`. ### Naloga Za ustvarjanje veljavnega novega računa sta potrebni 2 obvezni polji: uporabniško ime in valuta, ostala polja so neobvezna. Posodobite HTML obrazca z uporabo atributa `required` in besedila v oznaki polja, da: ```html ... ``` Čeprav ta specifična implementacija strežnika ne uveljavlja posebnih omejitev glede največje dolžine polj, je vedno dobra praksa določiti razumne omejitve za vnos besedila uporabnika. Dodajte atribut `maxlength` v besedilna polja: ```html ... ... ``` Zdaj, če pritisnete gumb *Registriraj* in polje ne upošteva pravila validacije, ki smo ga določili, bi morali videti nekaj takega: ![Posnetek zaslona, ki prikazuje napako validacije pri poskusu oddaje obrazca](../../../../translated_images/validation-error.8bd23e98d416c22f80076d04829a4bb718e0e550fd622862ef59008ccf0d5dce.sl.png) Validacija, ki se izvede *preden* se podatki pošljejo na strežnik, se imenuje **validacija na strani odjemalca**. Vendar pa ni vedno mogoče izvesti vseh preverjanj brez pošiljanja podatkov. Na primer, tukaj ne moremo preveriti, ali račun z istim uporabniškim imenom že obstaja, ne da bi poslali zahtevo na strežnik. Dodatna validacija, ki se izvede na strežniku, se imenuje **validacija na strani strežnika**. Običajno je treba implementirati obe vrsti validacije, in čeprav validacija na strani odjemalca izboljša uporabniško izkušnjo z zagotavljanjem takojšnjih povratnih informacij uporabniku, je validacija na strani strežnika ključna za zagotavljanje, da so podatki uporabnika, s katerimi delate, zanesljivi in varni. --- ## 🚀 Izziv Prikažite sporočilo o napaki v HTML-ju, če uporabnik že obstaja. Tukaj je primer, kako lahko končna stran za prijavo izgleda po nekaj oblikovanja: ![Posnetek zaslona strani za prijavo po dodajanju CSS stilov](../../../../translated_images/result.96ef01f607bf856aa9789078633e94a4f7664d912f235efce2657299becca483.sl.png) ## Kviz po predavanju [Kviz po predavanju](https://ff-quizzes.netlify.app/web/quiz/44) ## Pregled in samostojno učenje Razvijalci so postali zelo ustvarjalni pri svojih prizadevanjih za gradnjo obrazcev, še posebej glede strategij validacije. Spoznajte različne tokove obrazcev z raziskovanjem [CodePen](https://codepen.com); ali lahko najdete zanimive in navdihujoče obrazce? ## Naloga [Oblikujte svojo bančno aplikacijo](assignment.md) --- **Omejitev odgovornosti**: Ta dokument je bil preveden z uporabo storitve za prevajanje z umetno inteligenco [Co-op Translator](https://github.com/Azure/co-op-translator). Čeprav si prizadevamo za natančnost, vas prosimo, da upoštevate, da lahko avtomatizirani prevodi vsebujejo napake ali netočnosti. Izvirni dokument v njegovem maternem jeziku je treba obravnavati kot avtoritativni vir. Za ključne informacije priporočamo profesionalni človeški prevod. Ne prevzemamo odgovornosti za morebitna nesporazumevanja ali napačne razlage, ki bi nastale zaradi uporabe tega prevoda.