# Bouw een Bankapp Deel 3: Methoden voor het Ophalen en Gebruiken van Gegevens ## Pre-Les Quiz [Pre-les quiz](https://ff-quizzes.netlify.app/web/quiz/45) ### Introductie Aan de kern van elke webapplicatie staat *data*. Data kan vele vormen aannemen, maar het hoofddoel is altijd om informatie aan de gebruiker te tonen. Met webapps die steeds interactiever en complexer worden, is hoe de gebruiker toegang krijgt tot en interactie heeft met informatie een belangrijk onderdeel van webontwikkeling. In deze les gaan we bekijken hoe we gegevens asynchroon van een server kunnen ophalen en deze gegevens kunnen gebruiken om informatie op een webpagina weer te geven zonder de HTML opnieuw te laden. ### Vereisten Je moet het [Login- en Registratieformulier](../2-forms/README.md) van de webapp hebben gebouwd voor deze les. Je moet ook [Node.js](https://nodejs.org) installeren en [de server-API](../api/README.md) lokaal uitvoeren om toegang te krijgen tot accountgegevens. Je kunt testen of de server correct werkt door dit commando in een terminal uit te voeren: ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## AJAX en gegevens ophalen Traditionele websites werken de weergegeven inhoud bij wanneer de gebruiker een link selecteert of gegevens indient via een formulier, door de volledige HTML-pagina opnieuw te laden. Elke keer dat nieuwe gegevens moeten worden geladen, retourneert de webserver een volledig nieuwe HTML-pagina die door de browser moet worden verwerkt, wat de huidige gebruikersactie onderbreekt en interacties tijdens het herladen beperkt. Deze workflow wordt ook wel een *Multi-Page Application* of *MPA* genoemd.  Toen webapplicaties complexer en interactiever begonnen te worden, ontstond een nieuwe techniek genaamd [AJAX (Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming)). Deze techniek stelt webapps in staat om gegevens asynchroon van een server te verzenden en op te halen met JavaScript, zonder de HTML-pagina opnieuw te laden, wat resulteert in snellere updates en soepelere gebruikersinteracties. Wanneer nieuwe gegevens van de server worden ontvangen, kan de huidige HTML-pagina ook worden bijgewerkt met JavaScript via de [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) API. In de loop van de tijd is deze aanpak geëvolueerd tot wat nu een [*Single-Page Application* of *SPA*](https://en.wikipedia.org/wiki/Single-page_application) wordt genoemd.  Toen AJAX voor het eerst werd geïntroduceerd, was de enige beschikbare API om gegevens asynchroon op te halen [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Maar moderne browsers implementeren nu ook de meer handige en krachtige [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), die gebruikmaakt van promises en beter geschikt is voor het manipuleren van JSON-gegevens. > Hoewel alle moderne browsers de `Fetch API` ondersteunen, is het altijd een goed idee om de [compatibiliteitstabel op caniuse.com](https://caniuse.com/fetch) te controleren als je wilt dat je webapplicatie werkt op oudere browsers. ### Taak In [de vorige les](../2-forms/README.md) hebben we het registratieformulier geïmplementeerd om een account aan te maken. We gaan nu code toevoegen om in te loggen met een bestaand account en de gegevens op te halen. Open het bestand `app.js` en voeg een nieuwe `login`-functie toe: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; } ``` Hier beginnen we met het ophalen van het formulier-element met `getElementById()`, en vervolgens halen we de gebruikersnaam op uit de invoer met `loginForm.user.value`. Elk formuliercontrole-element kan worden benaderd via zijn naam (ingesteld in de HTML met het `name`-attribuut) als een eigenschap van het formulier. Net zoals we deden voor de registratie, maken we een andere functie om een serververzoek uit te voeren, maar deze keer om de accountgegevens op te halen: ```js 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' }; } } ``` We gebruiken de `fetch` API om de gegevens asynchroon van de server op te halen, maar deze keer hebben we geen extra parameters nodig behalve de URL die we willen aanroepen, omdat we alleen gegevens opvragen. Standaard maakt `fetch` een [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET) HTTP-verzoek, wat precies is wat we hier nodig hebben. ✅ `encodeURIComponent()` is een functie die speciale tekens voor een URL ontsnapt. Welke problemen zouden we kunnen tegenkomen als we deze functie niet aanroepen en de `user`-waarde direct in de URL gebruiken? Laten we nu onze `login`-functie bijwerken om `getAccount` te gebruiken: ```js 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'); } ``` Omdat `getAccount` een asynchrone functie is, moeten we deze combineren met het `await`-keyword om te wachten op het serverresultaat. Zoals bij elk serververzoek, moeten we ook omgaan met foutgevallen. Voor nu voegen we alleen een logbericht toe om de fout weer te geven en komen we hier later op terug. Vervolgens moeten we de gegevens ergens opslaan zodat we ze later kunnen gebruiken om de dashboardinformatie weer te geven. Omdat de `account`-variabele nog niet bestaat, maken we een globale variabele bovenaan ons bestand: ```js let account = null; ``` Nadat de gebruikersgegevens in een variabele zijn opgeslagen, kunnen we van de *login*-pagina naar het *dashboard* navigeren met behulp van de `navigate()`-functie die we al hebben. Ten slotte moeten we onze `login`-functie aanroepen wanneer het loginformulier wordt ingediend, door de HTML te wijzigen: ```html