18 KiB
Membangun Aplikasi Perbankan Bagian 3: Metode Mengambil dan Menggunakan Data
Kuis Pra-Pelajaran
Pendahuluan
Di inti setiap aplikasi web terdapat data. Data dapat berbentuk berbagai macam, tetapi tujuan utamanya selalu untuk menampilkan informasi kepada pengguna. Dengan aplikasi web yang semakin interaktif dan kompleks, bagaimana pengguna mengakses dan berinteraksi dengan informasi kini menjadi bagian penting dari pengembangan web.
Dalam pelajaran ini, kita akan melihat cara mengambil data dari server secara asinkron, dan menggunakan data ini untuk menampilkan informasi di halaman web tanpa memuat ulang HTML.
Prasyarat
Anda perlu telah membangun bagian Formulir Login dan Registrasi dari aplikasi web untuk pelajaran ini. Anda juga perlu menginstal Node.js dan menjalankan server API secara lokal agar Anda mendapatkan data akun.
Anda dapat menguji apakah server berjalan dengan benar dengan menjalankan perintah ini di terminal:
curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result
AJAX dan Pengambilan Data
Situs web tradisional memperbarui konten yang ditampilkan ketika pengguna memilih tautan atau mengirimkan data menggunakan formulir, dengan memuat ulang seluruh halaman HTML. Setiap kali data baru perlu dimuat, server web mengembalikan halaman HTML baru yang harus diproses oleh browser, mengganggu tindakan pengguna saat ini dan membatasi interaksi selama pemuatan ulang. Alur kerja ini juga disebut sebagai Multi-Page Application atau MPA.
Ketika aplikasi web mulai menjadi lebih kompleks dan interaktif, muncul teknik baru yang disebut AJAX (Asynchronous JavaScript and XML). Teknik ini memungkinkan aplikasi web untuk mengirim dan mengambil data dari server secara asinkron menggunakan JavaScript, tanpa harus memuat ulang halaman HTML, menghasilkan pembaruan yang lebih cepat dan interaksi pengguna yang lebih mulus. Ketika data baru diterima dari server, halaman HTML saat ini juga dapat diperbarui dengan JavaScript menggunakan API DOM. Seiring waktu, pendekatan ini berkembang menjadi apa yang sekarang disebut Single-Page Application atau SPA.
Ketika AJAX pertama kali diperkenalkan, satu-satunya API yang tersedia untuk mengambil data secara asinkron adalah XMLHttpRequest
. Namun, browser modern sekarang juga mengimplementasikan Fetch
API yang lebih nyaman dan kuat, menggunakan promises dan lebih cocok untuk memanipulasi data JSON.
Meskipun semua browser modern mendukung
Fetch API
, jika Anda ingin aplikasi web Anda bekerja di browser lama atau lawas, selalu merupakan ide yang baik untuk memeriksa tabel kompatibilitas di caniuse.com terlebih dahulu.
Tugas
Dalam pelajaran sebelumnya kita telah mengimplementasikan formulir registrasi untuk membuat akun. Sekarang kita akan menambahkan kode untuk login menggunakan akun yang sudah ada, dan mengambil datanya. Buka file app.js
dan tambahkan fungsi login
baru:
async function login() {
const loginForm = document.getElementById('loginForm')
const user = loginForm.user.value;
}
Di sini kita mulai dengan mengambil elemen formulir menggunakan getElementById()
, lalu kita mendapatkan nama pengguna dari input dengan loginForm.user.value
. Setiap kontrol formulir dapat diakses berdasarkan namanya (diatur di HTML menggunakan atribut name
) sebagai properti dari formulir.
Dengan cara yang mirip dengan apa yang kita lakukan untuk registrasi, kita akan membuat fungsi lain untuk melakukan permintaan server, tetapi kali ini untuk mengambil data akun:
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' };
}
}
Kita menggunakan fetch
API untuk meminta data secara asinkron dari server, tetapi kali ini kita tidak memerlukan parameter tambahan selain URL yang akan dipanggil, karena kita hanya mengambil data. Secara default, fetch
membuat permintaan HTTP GET
, yang sesuai dengan kebutuhan kita di sini.
✅ encodeURIComponent()
adalah fungsi yang menghindari karakter khusus untuk URL. Masalah apa yang mungkin terjadi jika kita tidak memanggil fungsi ini dan langsung menggunakan nilai user
dalam URL?
Sekarang mari kita perbarui fungsi login
kita untuk menggunakan 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');
}
Pertama, karena getAccount
adalah fungsi asinkron, kita perlu mencocokkannya dengan kata kunci await
untuk menunggu hasil server. Seperti halnya permintaan server, kita juga harus menangani kasus kesalahan. Untuk saat ini kita hanya akan menambahkan pesan log untuk menampilkan kesalahan, dan kembali ke sana nanti.
Kemudian kita harus menyimpan data di suatu tempat agar kita dapat menggunakannya nanti untuk menampilkan informasi dashboard. Karena variabel account
belum ada, kita akan membuat variabel global untuk itu di bagian atas file kita:
let account = null;
Setelah data pengguna disimpan ke dalam variabel, kita dapat bernavigasi dari halaman login ke dashboard menggunakan fungsi navigate()
yang sudah kita miliki.
Akhirnya, kita perlu memanggil fungsi login
kita ketika formulir login dikirimkan, dengan memodifikasi HTML:
<form id="loginForm" action="javascript:login()">
Uji apakah semuanya berfungsi dengan benar dengan mendaftarkan akun baru dan mencoba login menggunakan akun yang sama.
Sebelum melanjutkan ke bagian berikutnya, kita juga dapat melengkapi fungsi register
dengan menambahkan ini di bagian bawah fungsi:
account = result;
navigate('/dashboard');
✅ Tahukah Anda bahwa secara default, Anda hanya dapat memanggil API server dari domain dan port yang sama dengan halaman web yang Anda lihat? Ini adalah mekanisme keamanan yang diberlakukan oleh browser. Tapi tunggu, aplikasi web kita berjalan di localhost:3000
sedangkan server API berjalan di localhost:5000
, mengapa ini berfungsi? Dengan menggunakan teknik yang disebut Cross-Origin Resource Sharing (CORS), dimungkinkan untuk melakukan permintaan HTTP lintas asal jika server menambahkan header khusus ke respons, memungkinkan pengecualian untuk domain tertentu.
Pelajari lebih lanjut tentang API dengan mengikuti pelajaran ini
Memperbarui HTML untuk Menampilkan Data
Sekarang kita memiliki data pengguna, kita harus memperbarui HTML yang ada untuk menampilkannya. Kita sudah tahu cara mengambil elemen dari DOM menggunakan misalnya document.getElementById()
. Setelah Anda memiliki elemen dasar, berikut adalah beberapa API yang dapat Anda gunakan untuk memodifikasi atau menambahkan elemen anak ke dalamnya:
-
Dengan menggunakan properti
textContent
, Anda dapat mengubah teks dari sebuah elemen. Perhatikan bahwa mengubah nilai ini akan menghapus semua anak elemen (jika ada) dan menggantinya dengan teks yang diberikan. Dengan demikian, ini juga merupakan metode yang efisien untuk menghapus semua anak elemen dari elemen tertentu dengan menetapkan string kosong''
padanya. -
Dengan menggunakan
document.createElement()
bersama dengan metodeappend()
, Anda dapat membuat dan melampirkan satu atau lebih elemen anak baru.
✅ Dengan menggunakan properti innerHTML
dari sebuah elemen, juga dimungkinkan untuk mengubah konten HTML-nya, tetapi ini sebaiknya dihindari karena rentan terhadap serangan cross-site scripting (XSS).
Tugas
Sebelum melanjutkan ke layar dashboard, ada satu hal lagi yang harus kita lakukan di halaman login. Saat ini, jika Anda mencoba login dengan nama pengguna yang tidak ada, pesan ditampilkan di konsol tetapi bagi pengguna biasa tidak ada yang berubah dan Anda tidak tahu apa yang terjadi.
Mari kita tambahkan elemen placeholder di formulir login tempat kita dapat menampilkan pesan kesalahan jika diperlukan. Tempat yang baik adalah tepat sebelum tombol login <button>
:
...
<div id="loginError"></div>
<button>Login</button>
...
Elemen <div>
ini kosong, artinya tidak ada yang akan ditampilkan di layar sampai kita menambahkan konten ke dalamnya. Kita juga memberikan id
agar mudah diambil menggunakan JavaScript.
Kembali ke file app.js
dan buat fungsi pembantu baru updateElement
:
function updateElement(id, text) {
const element = document.getElementById(id);
element.textContent = text;
}
Fungsi ini cukup sederhana: diberikan id elemen dan teks, fungsi ini akan memperbarui konten teks dari elemen DOM dengan id
yang sesuai. Mari kita gunakan metode ini sebagai pengganti pesan kesalahan sebelumnya di fungsi login
:
if (data.error) {
return updateElement('loginError', data.error);
}
Sekarang jika Anda mencoba login dengan akun yang tidak valid, Anda akan melihat sesuatu seperti ini:
Sekarang kita memiliki teks kesalahan yang muncul secara visual, tetapi jika Anda mencobanya dengan pembaca layar, Anda akan melihat bahwa tidak ada yang diumumkan. Agar teks yang ditambahkan secara dinamis ke halaman dapat diumumkan oleh pembaca layar, teks tersebut perlu menggunakan sesuatu yang disebut Live Region. Di sini kita akan menggunakan jenis live region tertentu yang disebut alert:
<div id="loginError" role="alert"></div>
Terapkan perilaku yang sama untuk kesalahan fungsi register
(jangan lupa untuk memperbarui HTML).
Menampilkan Informasi di Dashboard
Dengan menggunakan teknik yang baru saja kita lihat, kita juga akan menangani penampilan informasi akun di halaman dashboard.
Berikut adalah seperti apa objek akun yang diterima dari server:
{
"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 }
],
}
Catatan: untuk mempermudah pekerjaan Anda, Anda dapat menggunakan akun
test
yang sudah ada dan telah diisi dengan data.
Tugas
Mari kita mulai dengan mengganti bagian "Balance" di HTML untuk menambahkan elemen placeholder:
<section>
Balance: <span id="balance"></span><span id="currency"></span>
</section>
Kita juga akan menambahkan bagian baru tepat di bawahnya untuk menampilkan deskripsi akun:
<h2 id="description"></h2>
✅ Karena deskripsi akun berfungsi sebagai judul untuk konten di bawahnya, itu ditandai secara semantik sebagai heading. Pelajari lebih lanjut tentang bagaimana struktur heading penting untuk aksesibilitas, dan lihat secara kritis halaman untuk menentukan apa lagi yang bisa menjadi heading.
Selanjutnya, kita akan membuat fungsi baru di app.js
untuk mengisi placeholder:
function updateDashboard() {
if (!account) {
return navigate('/login');
}
updateElement('description', account.description);
updateElement('balance', account.balance.toFixed(2));
updateElement('currency', account.currency);
}
Pertama, kita memeriksa bahwa kita memiliki data akun yang kita butuhkan sebelum melangkah lebih jauh. Kemudian kita menggunakan fungsi updateElement()
yang kita buat sebelumnya untuk memperbarui HTML.
Untuk membuat tampilan saldo lebih rapi, kita menggunakan metode
toFixed(2)
untuk memaksa menampilkan nilai dengan 2 digit setelah titik desimal.
Sekarang kita perlu memanggil fungsi updateDashboard()
kita setiap kali halaman dashboard dimuat. Jika Anda sudah menyelesaikan tugas pelajaran 1, ini seharusnya mudah, jika tidak, Anda dapat menggunakan implementasi berikut.
Tambahkan kode ini di akhir fungsi updateRoute()
:
if (typeof route.init === 'function') {
route.init();
}
Dan perbarui definisi rute dengan:
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard', init: updateDashboard }
};
Dengan perubahan ini, setiap kali halaman dashboard ditampilkan, fungsi updateDashboard()
dipanggil. Setelah login, Anda seharusnya dapat melihat saldo akun, mata uang, dan deskripsi.
Membuat Baris Tabel Secara Dinamis dengan Template HTML
Dalam pelajaran pertama, kita menggunakan template HTML bersama dengan metode appendChild()
untuk mengimplementasikan navigasi dalam aplikasi kita. Template juga dapat lebih kecil dan digunakan untuk mengisi bagian halaman yang berulang secara dinamis.
Kita akan menggunakan pendekatan serupa untuk menampilkan daftar transaksi dalam tabel HTML.
Tugas
Tambahkan template baru di <body>
HTML:
<template id="transaction">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</template>
Template ini mewakili satu baris tabel, dengan 3 kolom yang ingin kita isi: tanggal, objek, dan jumlah dari transaksi.
Kemudian, tambahkan properti id
ini ke elemen <tbody>
tabel dalam template dashboard untuk mempermudah pencarian menggunakan JavaScript:
<tbody id="transactions"></tbody>
HTML kita sudah siap, mari kita beralih ke kode JavaScript dan membuat fungsi baru 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;
}
Fungsi ini melakukan persis seperti namanya: menggunakan template yang kita buat sebelumnya, fungsi ini membuat baris tabel baru dan mengisi isinya menggunakan data transaksi. Kita akan menggunakan ini dalam fungsi updateDashboard()
kita untuk mengisi tabel:
const transactionsRows = document.createDocumentFragment();
for (const transaction of account.transactions) {
const transactionRow = createTransactionRow(transaction);
transactionsRows.appendChild(transactionRow);
}
updateElement('transactions', transactionsRows);
Di sini kita menggunakan metode document.createDocumentFragment()
yang membuat fragmen DOM baru yang dapat kita kerjakan, sebelum akhirnya melampirkannya ke tabel HTML kita.
Masih ada satu hal lagi yang harus kita lakukan sebelum kode ini dapat bekerja, karena fungsi updateElement()
kita saat ini hanya mendukung konten teks. Mari kita ubah sedikit kodenya:
function updateElement(id, textOrNode) {
const element = document.getElementById(id);
element.textContent = ''; // Removes all children
element.append(textOrNode);
}
Kita menggunakan metode append()
karena memungkinkan untuk melampirkan teks atau DOM Nodes ke elemen induk, yang sempurna untuk semua kasus penggunaan kita.
Jika Anda mencoba menggunakan akun test
untuk login, Anda sekarang seharusnya melihat daftar transaksi di dashboard 🎉.
🚀 Tantangan
Bekerja sama untuk membuat halaman dashboard terlihat seperti aplikasi perbankan yang nyata. Jika Anda sudah menata aplikasi Anda, cobalah menggunakan media queries untuk menciptakan desain responsif yang berfungsi dengan baik di perangkat desktop maupun mobile.
Berikut adalah contoh halaman dashboard yang sudah ditata:
Kuis Setelah Kuliah
Tugas
Refactor dan beri komentar pada kode Anda
Penafian:
Dokumen ini telah diterjemahkan menggunakan layanan terjemahan AI Co-op Translator. Meskipun kami berupaya untuk memberikan hasil yang akurat, harap diperhatikan bahwa terjemahan otomatis mungkin mengandung kesalahan atau ketidakakuratan. Dokumen asli dalam bahasa aslinya harus dianggap sebagai sumber yang berwenang. Untuk informasi yang bersifat kritis, disarankan menggunakan jasa terjemahan manusia profesional. Kami tidak bertanggung jawab atas kesalahpahaman atau penafsiran yang keliru yang timbul dari penggunaan terjemahan ini.