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/hr/7-bank-project/3-data
leestott c0ca49b2cc
🌐 Update translations via Co-op Translator
3 weeks ago
..
README.md 🌐 Update translations via Co-op Translator 3 weeks ago
assignment.md 🌐 Update translations via Co-op Translator 3 weeks ago

README.md

Izgradnja bankovne aplikacije, dio 3: Metode dohvaćanja i korištenja podataka

Kviz prije predavanja

Kviz prije predavanja

Uvod

U središtu svake web aplikacije nalaze se podaci. Podaci mogu imati različite oblike, ali njihova glavna svrha uvijek je prikazivanje informacija korisniku. Kako web aplikacije postaju sve interaktivnije i složenije, način na koji korisnik pristupa i komunicira s informacijama postaje ključni dio razvoja weba.

U ovoj lekciji vidjet ćemo kako asinkrono dohvatiti podatke sa servera i koristiti te podatke za prikaz informacija na web stranici bez ponovnog učitavanja HTML-a.

Preduvjeti

Za ovu lekciju trebate izraditi dio web aplikacije Obrazac za prijavu i registraciju. Također trebate instalirati Node.js i pokrenuti API server lokalno kako biste dobili podatke o korisničkim računima.

Možete provjeriti radi li server ispravno izvršavanjem ove naredbe u terminalu:

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

AJAX i dohvaćanje podataka

Tradicionalne web stranice ažuriraju prikazani sadržaj kada korisnik odabere poveznicu ili pošalje podatke putem obrasca, ponovno učitavajući cijelu HTML stranicu. Svaki put kada je potrebno učitati nove podatke, web server vraća potpuno novu HTML stranicu koju preglednik mora obraditi, prekidajući trenutnu korisničku akciju i ograničavajući interakcije tijekom učitavanja. Ovaj način rada naziva se višestranična aplikacija ili MPA.

Radni tijek ažuriranja u višestraničnoj aplikaciji

Kako su web aplikacije postajale složenije i interaktivnije, pojavila se nova tehnika nazvana AJAX (Asynchronous JavaScript and XML). Ova tehnika omogućuje web aplikacijama slanje i dohvaćanje podataka sa servera asinkrono pomoću JavaScripta, bez potrebe za ponovnim učitavanjem HTML stranice, što rezultira bržim ažuriranjima i glatkijim korisničkim interakcijama. Kada se novi podaci dobiju sa servera, trenutna HTML stranica može se ažurirati pomoću JavaScripta koristeći DOM API. S vremenom se ovaj pristup razvio u ono što se danas naziva jednostranična aplikacija ili SPA.

Radni tijek ažuriranja u jednostraničnoj aplikaciji

Kada je AJAX prvi put uveden, jedini dostupni API za asinkrono dohvaćanje podataka bio je XMLHttpRequest. No moderni preglednici sada implementiraju praktičniji i moćniji Fetch API, koji koristi obećanja (promises) i bolje je prilagođen za manipulaciju JSON podacima.

Iako svi moderni preglednici podržavaju Fetch API, ako želite da vaša web aplikacija radi na starijim preglednicima, uvijek je dobra ideja provjeriti tablicu kompatibilnosti na caniuse.com.

Zadatak

U prethodnoj lekciji implementirali smo obrazac za registraciju kako bismo kreirali korisnički račun. Sada ćemo dodati kod za prijavu koristeći postojeći račun i dohvaćanje njegovih podataka. Otvorite datoteku app.js i dodajte novu funkciju login:

async function login() {
  const loginForm = document.getElementById('loginForm')
  const user = loginForm.user.value;
}

Ovdje započinjemo dohvaćanjem elementa obrasca pomoću getElementById(), a zatim dobivamo korisničko ime iz unosa pomoću loginForm.user.value. Svaki kontrolni element obrasca može se pristupiti putem njegovog imena (postavljenog u HTML-u pomoću atributa name) kao svojstva obrasca.

Na sličan način kao što smo učinili za registraciju, kreirat ćemo drugu funkciju za izvršavanje zahtjeva prema serveru, ali ovaj put za dohvaćanje podataka o računu:

async function getAccount(user) {
  try {
    const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user));
    return await response.json();
  } catch (error) {
    return { error: error.message || 'Unknown error' };
  }
}

Koristimo fetch API za asinkrono dohvaćanje podataka sa servera, ali ovaj put ne trebamo dodatne parametre osim URL-a koji pozivamo, jer samo tražimo podatke. Prema zadanim postavkama, fetch kreira HTTP zahtjev tipa GET, što je upravo ono što nam treba.

encodeURIComponent() je funkcija koja kodira posebne znakove za URL. Koje probleme bismo mogli imati ako ne pozovemo ovu funkciju i izravno koristimo vrijednost user u URL-u?

Sada ćemo ažurirati našu funkciju login kako bismo koristili getAccount:

async function login() {
  const loginForm = document.getElementById('loginForm')
  const user = loginForm.user.value;
  const data = await getAccount(user);

  if (data.error) {
    return console.log('loginError', data.error);
  }

  account = data;
  navigate('/dashboard');
}

Prvo, budući da je getAccount asinkrona funkcija, moramo je uskladiti s ključnom riječi await kako bismo pričekali rezultat servera. Kao i kod svakog zahtjeva prema serveru, također moramo obraditi slučajeve pogrešaka. Za sada ćemo samo dodati poruku u log za prikaz pogreške i vratiti se na to kasnije.

Zatim moramo spremiti podatke negdje kako bismo ih kasnije mogli koristiti za prikaz informacija na nadzornoj ploči. Budući da varijabla account još ne postoji, kreirat ćemo globalnu varijablu na vrhu naše datoteke:

let account = null;

Nakon što su korisnički podaci spremljeni u varijablu, možemo se prebaciti s login stranice na dashboard koristeći funkciju navigate() koju već imamo.

Na kraju, trebamo pozvati našu funkciju login kada se obrazac za prijavu pošalje, modificirajući HTML:

<form id="loginForm" action="javascript:login()">

Testirajte da sve radi ispravno registracijom novog računa i pokušajem prijave koristeći isti račun.

Prije nego što prijeđemo na sljedeći dio, možemo dovršiti funkciju register dodavanjem ovoga na kraj funkcije:

account = result;
navigate('/dashboard');

Jeste li znali da prema zadanim postavkama možete pozivati server API-je samo s iste domene i porta kao web stranica koju pregledavate? Ovo je sigurnosni mehanizam koji provode preglednici. Ali čekajte, naša web aplikacija radi na localhost:3000, dok API server radi na localhost:5000, zašto to funkcionira? Koristeći tehniku nazvanu Cross-Origin Resource Sharing (CORS), moguće je izvršiti HTTP zahtjeve između različitih domena ako server doda posebne zaglavlja odgovoru, dopuštajući iznimke za određene domene.

Saznajte više o API-jima kroz ovu lekciju

Ažuriranje HTML-a za prikaz podataka

Sada kada imamo korisničke podatke, moramo ažurirati postojeći HTML kako bismo ih prikazali. Već znamo kako dohvatiti element iz DOM-a koristeći, na primjer, document.getElementById(). Nakon što imate osnovni element, evo nekih API-ja koje možete koristiti za njegovo modificiranje ili dodavanje podređenih elemenata:

  • Koristeći svojstvo textContent možete promijeniti tekst elementa. Imajte na umu da promjena ove vrijednosti uklanja sve podređene elemente (ako ih ima) i zamjenjuje ih pruženim tekstom. Kao takvo, ovo je također učinkovit način za uklanjanje svih podređenih elemenata danog elementa dodjeljivanjem praznog niza ''.

  • Koristeći document.createElement() zajedno s metodom append() možete kreirati i dodati jedan ili više novih podređenih elemenata.

Koristeći svojstvo innerHTML elementa također je moguće promijeniti njegov HTML sadržaj, ali ovo bi trebalo izbjegavati jer je ranjivo na napade cross-site scripting (XSS).

Zadatak

Prije nego što prijeđemo na ekran nadzorne ploče, postoji još jedna stvar koju bismo trebali učiniti na login stranici. Trenutno, ako pokušate prijaviti se s korisničkim imenom koje ne postoji, poruka se prikazuje u konzoli, ali za običnog korisnika ništa se ne mijenja i ne zna što se događa.

Dodajmo element rezerviranog mjesta u obrazac za prijavu gdje možemo prikazati poruku o pogrešci ako je potrebno. Dobro mjesto bilo bi neposredno prije gumba za prijavu <button>:

...
<div id="loginError"></div>
<button>Login</button>
...

Ovaj <div> element je prazan, što znači da se ništa neće prikazati na ekranu dok mu ne dodamo neki sadržaj. Također mu dajemo id kako bismo ga lako dohvatili pomoću JavaScripta.

Vratite se u datoteku app.js i kreirajte novu pomoćnu funkciju updateElement:

function updateElement(id, text) {
  const element = document.getElementById(id);
  element.textContent = text;
}

Ova funkcija je prilično jednostavna: s obzirom na id elementa i tekst, ažurirat će tekstualni sadržaj DOM elementa s odgovarajućim id. Koristimo ovu metodu umjesto prethodne poruke o pogrešci u funkciji login:

if (data.error) {
  return updateElement('loginError', data.error);
}

Sada, ako pokušate prijaviti se s nevažećim računom, trebali biste vidjeti nešto poput ovoga:

Snimka zaslona koja prikazuje poruku o pogrešci tijekom prijave

Sada imamo tekst pogreške koji se vizualno prikazuje, ali ako ga pokušate koristiti s čitačem ekrana, primijetit ćete da se ništa ne najavljuje. Kako bi tekst koji se dinamički dodaje stranici bio najavljen od strane čitača ekrana, potrebno je koristiti nešto što se zove Live Region. Ovdje ćemo koristiti specifičnu vrstu live regije nazvanu alert:

<div id="loginError" role="alert"></div>

Implementirajte isto ponašanje za pogreške funkcije register (ne zaboravite ažurirati HTML).

Prikaz informacija na nadzornoj ploči

Koristeći iste tehnike koje smo upravo vidjeli, također ćemo se pobrinuti za prikaz informacija o računu na stranici nadzorne ploče.

Ovako izgleda objekt računa dobiven sa servera:

{
  "user": "test",
  "currency": "$",
  "description": "Test account",
  "balance": 75,
  "transactions": [
    { "id": "1", "date": "2020-10-01", "object": "Pocket money", "amount": 50 },
    { "id": "2", "date": "2020-10-03", "object": "Book", "amount": -10 },
    { "id": "3", "date": "2020-10-04", "object": "Sandwich", "amount": -5 }
  ],
}

Napomena: kako biste si olakšali posao, možete koristiti unaprijed postojeći test račun koji je već popunjen podacima.

Zadatak

Započnimo zamjenom sekcije "Balance" u HTML-u kako bismo dodali elemente rezerviranog mjesta:

<section>
  Balance: <span id="balance"></span><span id="currency"></span>
</section>

Također ćemo dodati novu sekciju odmah ispod za prikaz opisa računa:

<h2 id="description"></h2>

Budući da opis računa funkcionira kao naslov za sadržaj ispod njega, označen je semantički kao naslov. Saznajte više o tome kako je struktura naslova važna za pristupačnost i kritički pogledajte stranicu kako biste utvrdili što bi još moglo biti naslov.

Zatim ćemo kreirati novu funkciju u app.js za popunjavanje rezerviranih mjesta:

function updateDashboard() {
  if (!account) {
    return navigate('/login');
  }

  updateElement('description', account.description);
  updateElement('balance', account.balance.toFixed(2));
  updateElement('currency', account.currency);
}

Prvo provjeravamo imamo li potrebne podatke o računu prije nego što nastavimo dalje. Zatim koristimo funkciju updateElement() koju smo ranije kreirali za ažuriranje HTML-a.

Kako bismo prikaz stanja učinili ljepšim, koristimo metodu toFixed(2) kako bismo prisilili prikaz vrijednosti s 2 znamenke nakon decimalne točke.

Sada trebamo pozvati našu funkciju updateDashboard() svaki put kada se učita stranica nadzorne ploče. Ako ste već završili zadatak iz lekcije 1, ovo bi trebalo biti jednostavno, inače možete koristiti sljedeću implementaciju.

Dodajte ovaj kod na kraj funkcije updateRoute():

if (typeof route.init === 'function') {
  route.init();
}

I ažurirajte definiciju ruta s:

const routes = {
  '/login': { templateId: 'login' },
  '/dashboard': { templateId: 'dashboard', init: updateDashboard }
};

Ovom promjenom, svaki put kada se prikaže stranica nadzorne ploče, poziva se funkcija updateDashboard(). Nakon prijave, tada biste trebali moći vidjeti stanje računa, valutu i opis.

Dinamičko stvaranje redaka tablice pomoću HTML predložaka

U prvoj lekciji koristili smo HTML predloške zajedno s metodom appendChild() za implementaciju navigacije u našoj aplikaciji. Predlošci također mogu biti manji i koristiti se za dinamičko popunjavanje ponavljajućih dijelova stranice.

Koristit ćemo sličan pristup za prikaz popisa transakcija u HTML tablici.

Zadatak

Dodajte novi predložak u HTML <body>:

<template id="transaction">
  <tr>
    <td></td>
    <td></td>
    <td></td>
  </tr>
</template>

Ovaj predložak predstavlja jedan redak tablice, s 3 stupca koje želimo popuniti: datum, objekt i iznos transakcije.

Zatim dodajte ovo svojstvo id elementu <tbody> tablice unutar predloška nadzorne ploče kako biste ga lakše pronašli pomoću JavaScripta:

<tbody id="transactions"></tbody>

Naš HTML je spreman, prebacimo se na JavaScript kod i kreirajmo novu funkciju createTransactionRow:

function createTransactionRow(transaction) {
  const template = document.getElementById('transaction');
  const transactionRow = template.content.cloneNode(true);
  const tr = transactionRow.querySelector('tr');
  tr.children[0].textContent = transaction.date;
  tr.children[1].textContent = transaction.object;
  tr.children[2].textContent = transaction.amount.toFixed(2);
  return transactionRow;
}

Ova funkcija radi upravo ono što njezino ime implicira: koristeći predložak koji smo ranije kreirali, stvara novi redak tablice i popunjava njegov sadržaj koristeći podatke o transakciji. Koristit ćemo ovo u našoj funkciji updateDashboard() za popunjavanje tablice:

const transactionsRows = document.createDocumentFragment();
for (const transaction of account.transactions) {
  const transactionRow = createTransactionRow(transaction);
  transactionsRows.appendChild(transactionRow);
}
updateElement('transactions', transactionsRows);

Ovdje koristimo metodu document.createDocumentFragment() koja stvara novi DOM fragment na kojem možemo raditi, prije nego što ga konačno priložimo našoj HTML tablici.

Još uvijek postoji jedna stvar koju moramo učiniti prije nego što ovaj kod može raditi, budući da naša funkcija updateElement() trenutno podržava samo tekstualni sadržaj. Promijenimo njezin kod malo:

function updateElement(id, textOrNode) {
  const element = document.getElementById(id);
  element.textContent = ''; // Removes all children
  element.append(textOrNode);
}

Koristimo metodu append() jer omogućuje priloženje teksta ili DOM čvorova roditeljskom elementu, što je savršeno za sve naše slučajeve. Ako pokušate koristiti test račun za prijavu, sada biste trebali vidjeti popis transakcija na nadzornoj ploči 🎉.


🚀 Izazov

Radite zajedno kako biste učinili da stranica nadzorne ploče izgleda kao prava aplikacija za bankarstvo. Ako ste već stilizirali svoju aplikaciju, pokušajte koristiti media queries kako biste stvorili responzivni dizajn koji dobro funkcionira i na stolnim računalima i na mobilnim uređajima.

Evo primjera stilizirane stranice nadzorne ploče:

Snimka zaslona primjera rezultata nadzorne ploče nakon stiliziranja

Kviz nakon predavanja

Kviz nakon predavanja

Zadatak

Refaktorirajte i komentirajte svoj kod


Odricanje od odgovornosti:
Ovaj dokument je preveden pomoću AI usluge za prevođenje Co-op Translator. Iako nastojimo osigurati točnost, imajte na umu da automatski prijevodi mogu sadržavati pogreške ili netočnosti. Izvorni dokument na izvornom jeziku treba smatrati autoritativnim izvorom. Za ključne informacije preporučuje se profesionalni prijevod od strane ljudskog prevoditelja. Ne preuzimamo odgovornost za bilo kakve nesporazume ili pogrešne interpretacije koje proizlaze iz korištenja ovog prijevoda.